动态代理

  • 最近要用AOP做一个BI打点上报,之前有看过AOP,但也只是看过而已,现在要用起来,还是得花时间好好看看的。首先Spring AOP底层就是通过动态代理机制实现的,所以现在先来了解一下动态代理的机制。

基于JDK的动态代理

  • 说白了就是为目标类创建一个代理对象,这种方式主要涉及到java.lang.reflect包中的Proxy类和InvocationHandler接口。至于这两个是什么东西,我直接用一个实例来说明吧。
  • 先是定义一个考试接口
public interface Exam{
    void startExam(String s);
}
  • 然后定义一个学生类,来实现上面的接口,这个就是我们的真实对象
public class Student implements Exam{
    @Override
    public void startExam(String s) {
        System.out.println("开始考试了!!");
    }
}
  • 现在要为上面这个真实对象创建一个代理对象,首先这个动态代理类必须实现上面的InvocationHandler接口。所以新建一个DynamicProxy类
public class DynamicProxy implements InvocationHandler {

    //目标类
    private Object target;
    public DynamicProxy(Object o){
        target = o;
    }

    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        System.out.println("监考开始");
        method.invoke (target, objects);
        System.out.println("监考结束");
        return target;
    }
}
  • 首先需要重写接口里面唯一的方法invoke(),方法里面有三个参数:
    Object o:我们创建的代理对象
    Method method:我们需要调用的真实对象的某个方法
    Object[] objects:上面方法传入的参数
  • 当我们通过代理对象调用真实对象的某个方法时,就会执行这里的invoke()方法,在这个方法里面,打印“监考开始”和“监考结束”是我们新加的逻辑(不属于Student类里面的内容),这样就可以动态地将自己的逻辑和业务逻辑(Student里面的)编织在一起。
  • 然后我们在看看主函数:
public class Test {
    public static void main(String[] args){
        Student target = new Student();
        DynamicProxy handler = new DynamicProxy(target);
        Exam proxy = (Exam) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                handler);
        proxy.startExam();
    }
}
  • 先是把新建的Student类传到DynamicProxy的构造方法里面去,我们需要代理哪个类就传哪个,因为最后是通过该真实对象来调用其方法的
  • 接着通过Proxy.newProxyInstance()来生成我们的代理对象,里面需要传入三个参数:
    ClassLoader loader:定义由哪个类加载器对生成的代理对象进行加载
    Class<?>[] interfaces:表示我们要给这个代理对象提供一组什么接口,代理对象实现了这组接口,那么我们就 可以调用里面的方法了
    InvocationHandler h:表示当代理对象调用方法时,会关联到哪一个InvocationHandler对象上
  • 最后就是利用代理对象来调用真实对象的方法,来看一下输出:
  • 在这里插入图片描述
  • 可以看到,输出的内容除了Student类里面的逻辑,还有我们自己新加的逻辑
  • 当我们通过代理对象来调用方法时,实际是委托其关联的InvocationHandler对象的invoke()方法来调用,并不是真实调用,这就是动态代理机制。
  • 我们知道,除了基于JDK动态代理,还有一种是基于CGLib动态代理。基于JDK这么好用,为什么还要再弄一种新的出来呢?这是因为基于JDK的代理只能为接口创建代理实例,你可以从上面就能清楚看到,Proxy.newProxyInstance()方法里面第二个参数传的是需要实现的接口数组。还是不明白的话可以看代理对象的创建过程,我们创建出来的代理对象其实是继承了Proxy类的,而Java有一条大名鼎鼎的法则:单一继承原则。

基于CGLib动态代理

  • 那么下面我们就来谈谈这种创建代理的方式
  • CGLib是采用非常底层的字节码技术,可以为一个类创建一个子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,并顺势织入我们新加的逻辑,确实有点酷。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值