关于AOP的一切,我与面试官的那一夜,难忘!
前言
Aop 是一个高频出现的技术点,不管在你的日常开发中还是在跳槽面试中,始终会看到它的影子。如此的高频,证明了它的重要性,既然这么重要,就没有理由不去搞清楚它。
在弄清楚 Aop 之前先来看看异步 @Async 和事务
@Transactional
的相关实现。
@Async实现
@Async
在这篇文章 你必须懂也可以懂的@Async
原理 中做过详细介绍,主要用来在应用实现异步功能。
@EnableAsync开启异步功能
若要在应用中使用 @Async
来实现异步功能,需要使用@EnableAsync
注解来开启异步功能
注入ProxyAsyncConfiguration
@EnableAsync
注解引入了异步配置选择器 AsyncConfigurationSelectorbing
并向IOC容器中注入了 ProxyAsyncConfiguration
创建异步注解处理器AsyncAnnotationBeanPostProcessor
ProxyAsyncConfiguration
中创建AsyncAnnotationBeanPostProcessor
Bean处理器
创建切面
创建切点
创建通知
Bean后置处理
@Transactional实现
@EnableAsync开启异步功能
注入ProxyTransactionManagementConfiguration配置类
创建切面
创建切点
创建通知
注入InfrastructureAdvisorAutoProxyCreator
InfrastructureAdvisorAutoProxyCreator
实现了 BeanPostProcessor
接口,因此会拦截所有的Bean进行处理
小结
通过对 @Async
和 @Transactional
的实现进行分析后,可以发现一个共同点:使用 @Enablexxx
注解来引入Bean处理器
和 切面 ,指定 切面 对应的 切点 和 通知 ;通过 Bean的后置处理方法 对符合切点的Bean生成代理并指明设置通知。【参考文档】
理解原理之后,就可以仿照着 @Async
和 @Transactional
来实现我们自己的需求,比如打印所有请求的请求参数、请求响应内容、请求耗时等。
类似功能已经可以实现了,但是实现起来还是比较复杂,首先你需要定义一个注解,紧接着要定义切面、切点、通知,然后定义Bean处理器,这么难还是放弃了吧。别着急,往下看看Spring Aop
的实现,你一定会爱不释手。
Aop实现
@EnableAspectJAutoProxy开启切面功能
注入AnnotationAwareAspectJAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator
实现 BeanPostProcessor
接口,用作Bean后置处理
Bean是否含有@Aspect注解
创建切点
创建通知
创建切面
Aop实现
@Component
@Aspect
public class SystemLogAspect {
/**
* 定义切点
*/
@Pointcut("execution(* com.boot.example.controller.*.*(..))")
public void SystemLogAspect() {
}
/**
* 定义通知
*/
@Before("SystemLogAspect()")
public void doBefore(JoinPoint joinPoint) {
}
/**
* 定义通知
*/
@AfterReturning("SystemLogAspect()")
public void doAfterReturning() {
}
/**
* 定义通知
*/
@Around("SystemLogAspect()")
public void doAround(ProceedingJoinPoint joinPoint) {
}
/**
* 定义通知
*/
@AfterThrowing(value = "SystemLogAspect()", throwing = "ex")
public void doThrowing(JoinPoint joinPoint, Exception ex) {
}
}
总结
-
使用
@EnableAspectJAutoProxy
注解开启Aop功能 -
定义Bean后置处理器
-
拦截所有被
@Aspect
注解标注的Bean -
获取Bean中所有没有被
@Pointcut
标注的方法
@Pointcut
@ Around
Before
@After
@AfterReturning
@AfterThrowing
value