深入理解AOP-代理的秘密

Posted 与叶老师学习JAVA

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入理解AOP-代理的秘密相关的知识,希望对你有一定的参考价值。

学过Spring框架的人都知道有AOP,面向切面编程,也理解切面[Aspect=Advice+PointCut]的公式,知道如何配置、使用,但是,这几个概念的核心原理你未必都懂,今天我们从代理的底层代码出发,来看看Spring中的AOP是怎么基于JDK的代理和CGLIB的代理来实现动态“织入”切面的能力的。


首先,我们来看一个简单的案例:

定义接口如下:

/*******

 * 业务接口

 */

public interface Calculate{

  int divide(int a, int b);

}

实现类如下:

/***************

 * 业务实现类

 */

public class CalculateImpl implement Calculate{

  @Override

  int divide(int a, int b) {

    int result = a / b;

    return result;

  }

}

现在,请思考一下?

如何在不改变业务实现类的代码情况下,给它添加日志功能,要求这个日志要在业务方法调用之前、之后、返回后或是在出现异常时都要记录下来,如何做到?


这是一个典型的AOP业务场景,在不改变原有类的情况下,动态添加新的功能,也就是日志,我们给出两种方案:


方案一:

根据接口的扩展原则,我们可以扩展出另一个类来实现Calculate 接口,并在此类中添加新的功能,把日志加上,如下:

/***************

 * 业务实现类2

 */

public class CalculateImpl2 implement Calculate{

  @Override

  int divide(int a, int b) {

    //记录日志

    try {

        int result = a / b;

         //记录日志

        return result;

    } catch (Exception e) {

        //记录日志

    } finally {

        //记录日志

    }

  }

}

然后,我们使用这个新类来调用业务方法,在不改变原来的类的基础上,确实也做到了添加新功能,但这种方式的缺点是“硬编码”,每加一种切面功能时,都要扩展出一个新类,当扩展的功能要交叉时,管理上很麻烦,所以,这种方式是一种静态的代理方式,也叫扩展,不是我们今天的主题,但是,在软件的架构上,这种思想还是很有用的,这里提一下。


方案二:【重点】

也就是采用动态代理,我们无需创建一个新的业务类来实现业务接口,从而在实现的业务方法中添加新功能,而是利用动态代理的能力,由JVM帮助我们在原有实现类的基础上,动态地“织入”我们的功能(这里是日志),听上去非常高大上,有没有! 那它是如何做到的呢?


Spring框架中使用两种方式来实现动态代理,分别是:


方式一:基于JDK的动态代理

此方式要求被代理的对象一定要实现一个或多个接口【Spring默认采用此方式】


方式二:基于CGLIB的动态代理

此方式对被代理对象无任何要求,功能强大【如果没有接口时,Spring采用此方式】




叶老师技术博客:http://www.teacherye.com 


以上是关于深入理解AOP-代理的秘密的主要内容,如果未能解决你的问题,请参考以下文章

Spring AOP深入理解之拦截器调用

对Spring AOP的进一步深入理解

对Spring AOP的进一步深入理解

spring aop —— 深入理解advisor

spring aop —— 深入理解advisor

Spring-----AOP深度理解