spring aop中this和target区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring aop中this和target区别相关的知识,希望对你有一定的参考价值。


前置条件

其实考虑这个问题的时候必须知道springaop 中存在2中代理,一个是jdk代理,一个cglib代理,并且这两者是有区别的,首先知道的一点,jdk代理是目标对象实现接口,也就是说jdk代码是基于接口的方式
同样一个问题:jdk代理,目标对象能继承一个父类,而不实现接口吗?为什么?

jdk代理生成代理对象

这里我们编写一生成的代码片段如下截图

public class Test 
public static void main(String[] args) throws IOException
byte[] wfgClasses = ProxyGenerator.generateProxyClass("wfgClass", new Class[]UserDao.class);

File wfgClasses1 = new File("/Users/wufagang/wfgClass.class");
System.out.println(wfgClasses1.getPath());
OutputStream out = new FileOutputStream(wfgClasses1);
out.write(wfgClasses);
out.flush();
out.close();

生成的代理对象的class文件如下

public final class wfgClass extends Proxy implements UserDao 
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;

public wfgClass(InvocationHandler var1) throws
super(var1);


public final boolean equals(Object var1) throws
try
return (Boolean)super.h.invoke(this, m1, new Object[]var1);
catch (RuntimeException | Error var3)
throw var3;
catch (Throwable var4)
throw new UndeclaredThrowableException(var4);



public final void saveUser() throws
try
super.h.invoke(this, m3, (Object[])null);
catch (RuntimeException | Error var2)
throw var2;
catch (Throwable var3)
throw new UndeclaredThrowableException(var3);



public final String toString() throws
try
return (String)super.h.invoke(this, m2, (Object[])null);
catch (RuntimeException | Error var2)
throw var2;
catch (Throwable var3)
throw new UndeclaredThrowableException(var3);



public final int hashCode() throws
try
return (Integer)super.h.invoke(this, m0, (Object[])null);
catch (RuntimeException | Error var2)
throw var2;
catch (Throwable var3)
throw new UndeclaredThrowableException(var3);



static
try
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("com.wfg.aop2.UserDao").getMethod("saveUser");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
catch (NoSuchMethodException var2)
throw new NoSuchMethodError(var2.getMessage());
catch (ClassNotFoundException var3)
throw new NoClassDefFoundError(var3.getMessage());


总结: public final class wfgClass extends Proxy implements UserDao
由此可以看到生成的代理对象继承Proxy类,实现我们定义的接口,java语言又是单继承的,所以jdk代理必须是实现接口不能是继承类

aop中this和target的区别

this表示代理对象
target表示目标对象

4.this JDK代理时,指向接口和代理类proxy,cglib代理时 指向接口和子类(不使用proxy)

5.target 指向接口和子类

此处需要注意的是,如果配置设置proxyTargetClass=false,或默认为false,则是用JDK代理,否则使用的是CGLIB代理

  • JDK代理的实现方式是基于接口实现,代理类继承Proxy,实现接口。
  • 而CGLIB继承被代理的类来实现。
  • 所以使用target会保证目标不变,关联对象不会受到这个设置的影响。
  • 但是使用this对象时,会根据该选项的设置,判断是否能找到对象。
    @Pointcut(“target(com.chenss.dao.IndexDaoImpl)”)
    //目标对象,也就是被代理的对象。限制目标对象为com.chenss.dao.IndexDaoImpl类@Pointcut(“this(com.chenss.dao.IndexDaoImpl)”)
    //当前对象,也就是代理对象,代理对象时通过代理目标对象的方式获取新的对象,与原值并非一个

这个比较难…proxy模式里面有两个重要的术语proxy Classtarget
ClassCGLIB和JDK有区别 JDK是基于接口 cglib是基于继承所有this可以在cglib作用

代码演示

这几天学习这一块我们应该可以很快写出来下面的代码没有难点

package com.wfg.aop2.dao;

/**
* @author wufagang
* @description
* @date 2021年04月24日 3:03 下午
*/
public interface IndexDao
public void saveUser(String user);
package com.wfg.aop2.dao;


import org.springframework.stereotype.Service;

/**
* @author wufagang
* @description
* @date 2021年04月24日 3:03 下午
*/
@Service
public class IndexDaoImpl implements IndexDao
@Override
public void saveUser(String user)
System.out.println("save user" + user);

package com.wfg.aop2;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
* @author wufagang
* @description
* @date 2021年04月24日 3:08 下午
*/
@Configuration
@ComponentScan("com.wfg.aop2")
@EnableAspectJAutoProxy(proxyTargetClass=false)
public class AppConfig
package com.wfg.aop2;

import com.wfg.aop2.dao.IndexDao;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/**
* @author wufagang
* @description
* @date 2021年04月24日 3:06 下午
*/
@Aspect
@Component
public class IndexAspect

@Before("this(com.wfg.aop2.dao.IndexDaoImpl)")
public void before()
System.out.println("before==============");


@After("target(com.wfg.aop2.dao.IndexDaoImpl)")
public void after()
System.out.println("after==============");

package com.wfg.aop2;

import com.wfg.aop2.dao.IndexDao;
import com.wfg.aop2.dao.IndexDaoImpl;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.lang.reflect.Proxy;

/**
* @author wufagang
* @description
* @date 2021年04月24日 3:09 下午
*/

public class Test2
public static void main(String[] args)
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
IndexDao bean = context.getBean(IndexDao.class);
System.out.println("类名称:"+bean.getClass().getName());
System.out.println("bean instanceof IndexDao :"+(bean instanceof IndexDao));
System.out.println("bean instanceof IndexDaoImpl :"+(bean instanceof IndexDaoImpl));
System.out.println("bean instanceof Proxy :"+(bean instanceof Proxy));
bean.saveUser("zhangsan");

代码测试:

@EnableAspectJAutoProxy(proxyTargetClass=false)

spring


@EnableAspectJAutoProxy(proxyTargetClass=true)

spring


通过上面的结果总结可知:

项目

this是否命中

target是否命中

是否属于Dao

是否属于Impl

是否属于Proxy

jdk代理


命中




cglib代理

命中

命中




深思:
@Before(“this(com.wfg.aop2.dao.IndexDaoImpl)”)我们将这个修改成
@Before(“this(com.wfg.aop2.dao.IndexDao)”) 此时不久可以命中了吗? java本身就是面向接口编程,但是this和target还有其他的区别吗?
目前我理解的修改成@Before(“this(com.wfg.aop2.dao.IndexDao)”)就没啥差别了,验证效果也是一样的。。。
更多的知识后面我们看源码的时候再说吧


以上是关于spring aop中this和target区别的主要内容,如果未能解决你的问题,请参考以下文章

Spring之AOP【二】

Spring AOP中pointcut expression表达式解析

Spring AOP切入点表达式

Spring AOP 中pointcut expression表达式解析及配置

SpringMVC中配aop拦截不生效,咋回事

Spring AOP中pointcut expression表达式解析 及匹配多个条件