spring aop中this和target区别

本文详细介绍了Spring AOP中的JDK代理和CGLIB代理的区别。JDK代理基于接口实现,代理类继承Proxy并实现目标接口,因此目标对象必须实现接口。而CGLIB则是通过继承目标类来创建代理对象。在使用this和target注解时,this指代代理对象,target指代目标对象。通过示例代码展示了不同代理方式下注解的效果,强调了proxyTargetClass属性对代理类型选择的影响。
摘要由CSDN通过智能技术生成

前置条件

其实考虑这个问题的时候必须知道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)
在这里插入图片描述
@EnableAspectJAutoProxy(proxyTargetClass=true)
在这里插入图片描述
通过上面的结果总结可知:

项目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)”)就没啥差别了,验证效果也是一样的。。。
更多的知识后面我们看源码的时候再说吧

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值