深入理解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-代理的秘密的主要内容,如果未能解决你的问题,请参考以下文章