描述 spring aop 的使用方法以及 spring 如何实现 aop 功能
基本概念
AOP 即 Aspect Oriented Programming,它是在不修改源代码的情况下给程序动态统一添加功能的一种技术。 AOP 的术语有
- 通知(或叫增强) Advice
想要通过 spring aop 增强的功能, 例如日志,事务,安全等 - 增强器 Advicsor
实现增强的功能。例如要实现日志,则需要实现了日志功能的增强器 - 连接点 JoinPoint
spring 中允许使用通知的地方,例如方法执行前,方法执行后 - 切入点 Pointcut
定义在连接点的基础上,例如一个类有 15 个方法,但并不是每一个方法都需要通知,切点就是为了筛选出连接点,选中要通知的方法 - 切面 Aspect
切面是通知和切入点的结合 - 引入 Introduction
允许向现有的类添加新方法属性 - 目标 Target
引入中所提到的目标类 - 代理 proxy
用来实现整个 AOP 的基础技术,spring aop 目前有 CGLIB 和 JDK 动态代理 - 织入 weaving
把切面应用到目标对象来创建新的代理对象的过程。spring 默认情况下是动态织入,即运行时织入。另外还有静态织入(即 jvm 启动时织入)和 LTW(即类加载时织入)
使用 spring aop
xml 方式
1 | public class AopDemo { |
1 |
|
aspectj 注解方式
通过 @Aspect 注解的方式配置 aop 功能
1 |
|
编程方式
通过编程的方式实现 aop, spring 的功能就是通过这种方式实现
1 | public class AopDemo { |
自定义方式
允许用户自定义 AOP
1 |
|
实现
打开 aop 功能
通过 @EnableAspectJAutoProxy 注解或 XML 的 <aop:config> 都可以打开 aop 功能。 两种方式分别将 AnnotationAwareAspectJAutoProxyCreator 和 AspectJAwareAdvisorAutoProxyCreator 注册到 bean factory。
AnnotationAwareAspectJAutoProxyCreator 是 AspectJAwareAdvisorAutoProxyCreator 的子类, AspectJAwareAdvisorAutoProxyCreator 实现了 SmartInstantiationAwareBeanPostProcessor 接口(BPP),重载 postProcessAfterInitialization 方法实现对 bean 的包装。
1 | public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport |
生成 proxy
proxy 通过 ProxyFactory 生成
1 | public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport |
被增强方法的调用
使用 CGLIB 创建代理的情况
代理方法的入口是 DynamicAdvisedInterceptor 的 intercept 方法。DynamicAdvisedInterceptor 是一个实现了 MethodInterceptor 接口的 CGLIB callback, 调用 CGLIB 生成的代理对象的方法时,一般情况下都先调用它
1 | private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable { |
使用 JDK 创建代理的情况
使用 JDK 代理时, 所有调用方法都通过 InvocationHandler 处理,而 JdkDynamicAopProxy 本身就实现了 InvocationHandler 接口。
1 | final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable { |
示例
@Async 注解可以使得方法异步执行,而不影响方法的代码逻辑,这是 AOP 的一个典型应用,示例代码如下
1 | public class AsyncDemoApp { |
@EnableAsync 通过 @Import(AsyncConfigurationSelector.class) 实现,AsyncConfigurationSelector 根据配置在 bean factory 注册 ProxyAsyncConfiguration 或 AspectJAsyncConfiguration (使用 AspectJ)。 Configuration 分别注册 AsyncAnnotationBeanPostProcessor 和 AnnotationAsyncExecutionAspect
AsyncAnnotationBeanPostProcessor 是 AbstractAdvisingBeanPostProcessor 的子类,是一个给 bean 包装异步调用的 BPP,它的 advisor 是 AsyncAnnotationAdvisor,AsyncAnnotationAdvisor 的 pointcut 是 AnnotationMatchingPointcut,advice 是 AnnotationAsyncExecutionInterceptor。
当调用这些方法时,AnnotationAsyncExecutionInterceptor 就会新建一个调用 @Async 方法的 Callable 对象,然后提交到线程池去执行。