Spring 注解编程AOP
-
AOP的常用注解 -
AOP的源码分析 - 事务的注解与源码分析
AOP的常用注解
Aspect-Oriented Programming 面向切面编程,主要包含切面
Aspect,切入点Pointcut以及通知(切入时机)Advice,通知包含方法执行之前Before、方法执行之后After、方法环绕Around,通知方法参数有JoinPoint,Around方法参数有ProceedingJoinPoint
JoinPoint只能放在方法的第一个参数,主要方法如下
getArgs()返回方法的参数getThis()返回代理对象getTarget()返回目标对象getSignature()返回通知方法的签名toString()返回通知方法有用描述ProceedingJoinPoint只能放在方法的第一个参数,主要方法如下
proceed(Object[] args)执行目标方法
@EnableAspectJAutoProxy
启用切面,相当于xml中aop:aspectj-autoproxy
1 | |
proxyTargetClass对应xml中属性proxy-target-class,是否启用CGLIBexposeProxy对应xml中属性expose-proxy,是否暴露代理,设置为true的时候,可以通过AopContext.currentProxy()获取代理实例(通过ThreadLocal进行实现的)
@Aspect
切面,横切多个类的关系的模块化
1 | |
相当于xml中
1 | |
@Pointcut
切点,执行方法的切点
1 | |
相当于xml中
1 | |
切入点表达式
execution切入表达式,这个Spring中最常用的execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)execution(public * *(..))所有包下的public方法execution(* set*(..))所有已set开头的方法`*execution(* com.xyz.service.AccountService.*(..))AccountService下的所有方法execution(* com.xyz.service.*.*(..))service包下的所有类的方法execution(* com.xyz.service..*.*(..))service包以及子包的所有类的方法
withinwithin(com.xyz.service.*)service包下的所有类的方法within(com.xyz.service.*)service包以及子包所有类的方法
this指定代理实现的接口this(com.xyz.service.AccountService)指定AccountService接口下的所有方法target执行目标对象实现的接口target(com.xyz.service.AccountService)指定AccountService接口下的所有方法args执行目标方法的参数args(java.io.Serializable)有Serializable参数的所有方法@target@target(org.springframework.transaction.annotation.Transactional)目标对象有@Transactional注解的类所有方法@within@within(org.springframework.transaction.annotation.Transactional)目标对象有@Transactional注解申明的类所有方法@annotation@annotation(org.springframework.transaction.annotation.Transactional)有@Transactional注解的所有方法@args@args(com.xyz.security.Classified)有@Classified注解的单参数方法bean- b
ean(*ServiceImpl)所有以ServiceImpl结尾Bean的所有方法
- b
@Before
在切点的方法之前执行方法
1 | |
相当于xml中
1 | |
@AfterReturning
在切点的方法执行返回执行
1 | |
相当于xml中
1 | |
@AfterThrowing
在切点的方法执行抛出异常执行
1 | |
相对于xml中
1 | |
@After
在切点方法执行之后执行,也就是在@AfterReturning或者@AfterThrowing之前执行
1 | |
相当于xml中
1 | |
@Around
在切点方法执行前后执行
1 | |
相当于xml中
1 | |
AOP的执行顺序
正常执行流程:@Around -> @Before -> @After -> @AfterReturning
异常执行流程:@Around -> @Before -> @After -> @AfterThrowing
切面的主要接口
PointCut 切入点
ClassFilter类的过滤器MethodMatcher方法的匹配器
Advice 通知
BeforeAdvice前置通知AfterAdvice后置通知AfterReturningAdvice执行返回通知ThrowsAdvice异常通知
MethodInterceptor 方法的拦截器(继承Advice)
MethodBeforeAdviceInterceptor方法前置拦截器AspectJAroundAdviceApectJ环绕拦截器AspectJAfterAdviceApectJ后置拦截器AfterReturningAdviceInterceptor后置返回拦截器AspectJAfterThrowingAdvice后置异常拦截器
Advisor 通知器
Advice通知
PointcutAdvisor 切入点通知器(继承Advisor)
Pointcut切入点
动态代理的主要接口
AopProxy Aop动态代理
JdkDynamicAopProxyJdk动态代理CglibAopProxyCglib动态代理ObjenesisCglibAopProxy扩展的Cglib动态代理
这个是通过
org.springframework.aop.framework.DefaultAopProxyFactory进行动态匹配生成,构建执行链org.springframework.aop.framework.DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice关联了Advisor
AOP的源码分析
@EnableAspectJAutoProxy
注解通过@Import(AspectJAutoProxyRegistrar.class)注册
- 实现
ImportBeanDefinitionRegistrar AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry)- 注册
org.springframework.aop.config.internalAutoProxyCreator——AnnotationAwareAspectJAutoProxyCreator,最高优先级
- 注册
AnnotationAwareAspectJAutoProxyCreator
实现主要接口
BeanFactoryAwareBeanFactory回调接口InstantiationAwareBeanPostProcessor实例化执行的接口BeanPostProcessorBean后置处理器
BeanFactoryAware BeanFactory回调接口
AbstractAdvisorAutoProxyCreator#setBeanFactoryAnnotationAwareAspectJAutoProxyCreator#initBeanFactoryReflectiveAspectJAdvisorFactory处理
Advice通知注解@Around、@Before、@After、@AfterReturning、@AfterThrowing构建了一个
PointcutAdvisor(InstantiationModelAwarePointcutAdvisorImpl)AspectJExpressionPointcutPointCut切点表达式Advice通知
BeanFactoryAspectJAdvisorsBuilderAdapter
InstantiationAwareBeanPostProcessor 实例化执行的接口
InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 实例化执行的方法
AbstractAutoProxyCreator#postProcessBeforeInstantiation
- 判断是否是通知Bean
Advice、Pointcut、Advisor、AopInfrastructureBean这几个类的子类@Aspect注解的类- bean的名词是否以bean的Class名称开头并且以
.ORIGINAL结束
- 是否需要跳过
- 获取
Advisor通知器列表(获取到了InstantiationModelAwarePointcutAdvisorImpl)
- 获取
- 是否自定义
TargetSourceCreator,若是有直接执行createProxy
BeanPostProcessor Bean后置处理器
BeanPostProcessor#postProcessAfterInitialization 初始化执行的方法
AbstractAutoProxyCreator#postProcessAfterInitialization
wrapIfNecessary- 判断是否是通知Bean
- 是否需要跳过
- 判断是否有
Advice通知的Bean创建代理createProxyDefaultAopProxyFactory#createAopProxyconfig.isProxyTargetClass()- 接口或者是Proxy的子类,使用
JdkDynamicAopProxy - 其他使用
ObjenesisCglibAopProxy
- 接口或者是Proxy的子类,使用
- 创建
JdkDynamicAopProxy
通过代码实现切面
实现一个PointAdvisor
1 | |
实现一个MethodInterceptor
1 | |
配置Bean信息
1 | |
若是不希望拦截所有的方法,自行实现Pointcut
1 | |
事务的注解与源码分析
事务的解决问题
脏读
一个线程在处理数据,事务还未提交;另一个线程可以读到此数据
重复读
一个线程读数据,另一个线程改数据,导致同一个线程获取的数据不一致。
幻读
一个线程读数据,另一个线程添加数据,导入同一个线程获取的数据条目不一致,多出来的条目称为幻行。
事务的隔离级别
Connection
READ_UNCOMMITTED读未提交的READ_COMMITTED读已提交REPEATABLE_READ重复读SERIALIZABLE串行事务的传播机制
TransactionDefinition
REQUIRED必须以事务执行,若有事务,以当前事务执行,没有事务重新启动新事务执行SUPPORTS支持事务执行,若有事务,用当前事务执行,没有事务不进行事务操作MANDATORY支持事务执行,若有事务,用当前事务执行,没有事务抛错REQUIRES_NEW以新事务执行NOT_SUPPORTED支持无事务执行NEVER无事务执行,有事务抛错NESTED若是有事务存在,嵌套事务执行
常用注解
@EnableTransactionManagement
开启事务的注解
@Transactional
启用事务的注解
源码分析
@EnableTransactionManagement
通过@Import(TransactionManagementConfigurationSelector.class)注册
PROXYJDK代理通知AutoProxyRegistrarAopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)注册
org.springframework.aop.config.internalAutoProxyCreator——InfrastructureAdvisorAutoProxyCreator优先级判断
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry)org.springframework.aop.config.internalAutoProxyCreator设置属性proxyTargetClass
ProxyTransactionManagementConfiguration注册如下的Bean
transactionAdvisor——BeanFactoryTransactionAttributeSourceAdvisor事务通知者TransactionAttributeSourceAdvice——TransactionInterceptor
transactionAttributeSource——AnnotationTransactionAttributeSourcetransactionInterceptor——TransactionInterceptor事务方法拦截器TransactionAttributeSourceTransactionManager
ASPECTJAspectJ代理通知AspectJJtaTransactionManagementConfigurationAspectJTransactionManagementConfiguration