回炉Spring-AOP及事务源码解读
一、AOP
AOP,面向切面编程
即拓展功能不通过修改源代码来实现。
采用横向抽取机制,取代了传统的纵向继承体系的重复性代码。在运行期间通过代理方式向目标类中织入增强代码。
实现一个AOP的步骤:
1、将需要增强的目标类和切面类都注入到Spring容器中,标注使Spring知道哪个是切面类,@Aspect(曾犯错,在切面类上没有标注@Component注解)
2、使用@Pointcut注解定义切点。切点分为execution方式和annotation方式
①:annotation方式
@Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
②:execution方式
@Pointcut("execution(* com.mutest.controller..*.*(..))")
第一个 * 号的位置:表示返回值类型,* 表示所有类型
包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,在本例中指 com.mutest.controller包、子包下所有类的方法
第二个 * 号的位置:表示类名,* 表示所有类
*(..):这个星号表示方法名,* 表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数
3、在切面类上的通知方法上标注通知注解(如@Around,@Before等),并在注解中指明切入点表达式(或切点方法)
4、开启基于注解的aop模式,在配置类上加上注解@EnableAspectJAutoProxy
注:(SpringBoot默认开启了基于注解的AOP模式,不用再启动类上再加@EnableAspectJAutoProxy)
@AfterReturning注解的returning可将增强方法的返回值映射到参数上
@AfterReturning(value = "pointCut()", returning = "result") public void afterReturning(Object result) throws Throwable {}
@AfterThrowing(value="pointCut()",throwing="exception")的throwing将增强方法的异常信息映射到参数上
获取切入点方法名:joinPoint.getSignature().getName()
获取方法入参:joinPoint.getArgs()
@Before("pointCut()") // 方法若有多个参数,JoinPoint一定要放在第一位 public void before(JoinPoint joinPoint) { String name = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); }
AOP原理:
@EnableAspectJAutoProxy注解做了什么?
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy {...}
@EnableAspectJAutoProxy往容器中导入了AspectJAutoProxyRegistrar,利用AspectJAutoProxyRegistrar自定义往容器中注册了name为org.springframework.aop.config.internalAutoProxyCreator,class为AnnotationAwareAspectJAutoProxyCreator的bean。
也就是说,@EnableAspectJAutoProxy往Spring容器中注册了AnnotationAwareAspectJAutoProxyCreator这个bean。
技巧:如果看到了Enable开头的注解,就看这个注解有没有往容器中注册一些组件,如果注册组件了,这些组件的功能是什么,如果具体功能搞明白了,那么这个注解的原理就清楚了。
那么既然@EnableAspectJAutoProxy往Spring容器中注册了AnnotationAwareAspectJAutoProxyCreator这个bean(从名字看是:注解装配切面代理创造器),那就看一下这个bean的功能是什么,源码走起:
AnnotationAwareAspectJAutoProxyCreator 的继承关系如下:
看到其祖先类实现了InstantiationAwareBeanPostProcessor 接口,而此接口又实现了BeanPostProcessor接口,而这个接口我们知道叫做后置处理器,后置处理器的功能就是在bean初始化的前后做一些工作。
抽象父类AbstractAutoProxyCreator 又实现了BeanFactoryAware,可以往代码中注入BeanFactory。
那么先重点看与setBeanFactory以及与后置处理器相关的逻辑,通过源码发现AbstractAutoProxyCreator有setBeanFactory()以及后置处理器相关的逻辑。而在AbstractAutoProxyCreator的子抽象类AbstractAdvisorAutoProxyCreator又重写了setBeanFactory()方法
public void setBeanFactory(BeanFactory beanFactory) { super.setBeanFactory(beanFactory); if (!(beanFactory instanceof ConfigurableListableBeanFactory)) { throw new IllegalArgumentException("AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory); } else { this.initBeanFactory((ConfigurableListableBeanFactory)beanFactory); } }
由于其子类AnnotationAwareAspectJAutoProxyCreator 重写了initBeanFactory方法,所以最终调用的是AnnotationAwareAspectJAutoProxyCreator 中的initBeanFactory方法中的逻辑:
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) { super.initBeanFactory(beanFactory); if (this.aspectJAdvisorFactory == null) { this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory); } this.aspectJAdvisorsBuilder = new AnnotationAwareAspectJAutoProxyCreator.BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory); }
断点看AOP的整个执行流程:
1、new AnnotationConfigApplicationContext(AopConfig.class); 创建Spring容器,接下来看其构造器逻辑
2、先注册配置类,然后调用refresh()方法刷新容器,接下来看refresh()的逻辑
3、invokeBeanFactoryPostProcessors(beanFactory);实例化并调用所有注册的BeanFactoryPostProcessor
4、registerBeanPostProcessors(beanFactory); 注册bean的后置处理器来拦截bean的创建
1):先获取ioc容器中已经定义了的所有实现BeanPostProcessor接口的后置处理器的name. String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
2):给容器中添加了额外的BeanPostProcessor beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
3):遍历所有的BeanPostProcessor,按照实现了PriorityOrdered接口的,和实现了Ordered接口的进行分组,分别保存在不同的List集合中
①:若实现了PriorityOrdered,则先创建其对象,当成普通bean注册到Spring容器中,然后将其放进priorityOrderedPostProcessors集合,若其又实现了MergedBeanDefinitionPostProcessor,将其再放进internalPostProcessors集合;
②:若其实现了Ordered接口,将其bean name放入orderedPostProcessorNames集合;
③:若两个接口都没实现,则将其bean name放进nonOrderedPostProcessorNames集合;
4):优先注册实现了PriorityOrdered接口的BeanPostProcessor作为bean的后置处理器到Spring容器中,再注册实现了Ordered接口的BeanPostProcessor,最后注册其他的BeanPostProcessor.
注册的BeanPostProcessor保存在AbstractBeanFactory的 private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();集合属性中
5):注册其实就是步骤3)中的根据其name获取BeanPostProcessor对象{BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);},实际上就是创建BeanPostProcessor对象然后将其保存在Spring容器中。
以创建name为internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】为例,看一下创建过程:
(1):创建bean的实例,getBean()——doGetBean()——getSingleton()——getObject()——createBean()——doCreateBean()
(2):populateBean:给bean的各种属性赋值
(3):initializeBean:初始化bean
①:invokeAwareMethods()判断bean是不是实现了xxxAware接口,如果实现了就调用相关的setXxx方法给bean的属性赋值
②:Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);应用bean的后置处理器的初始化前置方法,获取所有的后置处理器(之前注册保存在AbstractBeanFactory的List<BeanPostProcessor>属性中),遍历调用它们的postProcessBeforeInitialization()方法
③:invokeInitMethods(beanName, wrappedBean, mbd); 执行初始化方法,先@PostConstruct() 注解方法,然后如果实现了InitializingBean,执行afterPropertiesSet,再执行自定义的初始化方法(如果在@Bean注解指定了initMethod的话)
④:Object wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);应用bean的后置处理器的初始化后置方法,获取所有的后置处理器,遍历调用其postProcessAfterInitialization()方法
6):由于AnnotationAwareAspectJAutoProxyCreator实现了 BeanFactoryAware接口,所以在invokeAwareMethods()方法中,回到了上面说的调用其抽象父类AbstractAdvisorAutoProxyCreator重写的setBeanFactory()方法。然后走到了AnnotationAwareAspectJAutoProxyCreator 的initBeanFactory()方法,至此,BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功
7):最后将所有的BeanPostProcessor注册到BeanFactory中
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
-->beanFactory.addBeanPostProcessor(postProcessor);)
注册的BeanPostProcessor保存在AbstractBeanFactory的 private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();集合属性中
以上就是创建和注册AnnotationAwareAspectJAutoProxyCreator的过程。
接下来看其作为一个BeanPostProcessor如何影响bean的创建过程的:
5、finishBeanFactoryInitialization(beanFactory);完成BeanFactory初始化工作,创建剩下的单实例bean,为什么说是剩下的呢?因为BeanPostProcessors类型的bean在步骤4已经创建
完成了
1):preInstantiateSingletons()-->遍历获取容器中所有的beanDefinitionNames,遍历依此创建对象getBean(beanName); 在DefaultListableBeanFactory类中
2):getBean(beanName)-->doGetBean()-->getSingleton(beanName) ,在创建bean之前先尝试获取单实例Bean的实例,为什么呢?因为只要创建好的bean就会被缓存起来
①:先去JVM缓存 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); /** Cache of singleton objects: bean name to bean instance. */ 中去获取缓存的创建好了的单实例bean对象
②:若创建完成的单实例bean缓存中没有,再去当前创建bean池中去尝试获取。
当前创建bean池:private final Set<String> singletonsCurrentlyInCreation =Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16)); // 池中保存中的是 bean name
因为在创建单实例bean的时候会存在依赖注入的情况,为了避免循环依赖,Spring在创建bean的过程中,若发现有依赖bean,则尝试去创建依赖的bean,因此Spring将每一个正在创建的bean的beanName放在一个“当前创建bean池”中,bean在创建过程中,BeanName将一直存在这个池中。
③:如果当前线程创建bean池有,则尝试从提前创建单例bean缓存中加载bean:private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16); /** Cache of early singleton objects: bean name --> bean instance */
④:如果earlySingletonObjects 缓存中加载不成功,则再次尝试从singletonFactories中获取提前曝光的ObjectFactory,private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); /** Cache of singleton factories: bean name --> ObjectFactory */
如果根据beanName找到了ObjectFactory,则从ObjectFactory中获取bean实例,然后将其放在earlySingletonObjects 缓存中,再将其ObjectFactory从singletonFactories中移除。
因为Spring为了避免循环依赖,在Spring中创建bean的原则是不等bean创建完就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时候需要依赖上一个bean则直接使用ObjectFactory去获取依赖bean的实例。
3):createBean() 创建bean实例
①:Object bean=resolveBeforeInstantiation(beanName, mbdToUse); 参数:RootBeanDefinition mbdToUse,bean的定义信息。
方法的作用是:给BeanPostProcessor一个机会返回一个代理对象就不用创建其对象了。如果可以,直接返回代理对象,如果不能,则继续执行doCreateBean(beanName, mbdToUse, args);,其实现为:
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); }
这个方法的逻辑是:先拿到所有的后置处理器然后遍历,如果其中一个后置处理器实现了InstantiationAwareBeanPostProcessor接口,则执行这个后置处理器的postProcessBeforeInstantiation方法,如果返回了bean对象,则执行applyBeanPostProcessorsAfterInitialization并返回bean实例,结束bean的创建,不走下面的doCreateBean。
注意:InstantiationAwareBeanPostProcessor虽继承了BeanPostProcessor,但其定义了postProcessBeforeInstantiation和postProcessAfterInstantiation方法,与BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法不同,BeanPostProcessor的两个方法是在bean实例创建完成之后的初始化前后调用的,而InstantiationAwareBeanPostProcessor的两个方法是在创建bean实例之前尝试返回代理对象的。
这也是AnnotationAwareAspectJAutoProxyCreator的功能,在所有的bean创建之前会有一个拦截,尝试返回其代理对象
②:doCreateBean,真正的创建bean的实例,即上面4.5的流程
AnnotationAwareAspectJAutoProxyCreator做了什么事情?
一下逻辑都在create()方法中
1、每一个bean创建之前,都会调用postProcessBeforeInstantiation(); 代码在AbstractAutoProxyCreator#postProcessBeforeInstantiation
其处理逻辑是:
1):判断当前bean是否在advisedBean(保存了所有增强过的bean的缓存)中,private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
2):isInfrastructureClass(beanClass):判断当前bean是否是 基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean或者是否是切面(是否有@Aspect注解)
3):或者shouldSkip(beanClass, beanName):是否需要跳过
①:获取候选的增强器(切面里面的增强方法)List<Advisor> candidateAdvisors = findCandidateAdvisors();
②:遍历然后判断每一个增强器是否是AspectJPointcutAdvisor类型的,如果是,返回true,否则返回flase
③:而我们的增强器类型是:InstantiationModelAwarePointcutAdvisor,因此,shouldSkip方法永远返回false
2、执行doCreateBean方法,创建bean,并初始化
3、postProcessAfterInstantiation和postProcessBeforeInitialization一个返回true,一个返回bean对象本身,什么都没做
4、postProcessAfterInitialization方法:创建完对象并初始化后,调用它。代码在AbstractAutoProxyCreator#postProcessAfterInitialization 其逻辑是:
判断当前bean是否已经代理过,若没有则执行:return wrapIfNecessary(bean, beanName, cacheKey); 这个方法的作用是,封装bean如果必要的话,也就是在这里创建目标类的代理对象
1):Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);找到所有能应用到当前bean的增强方法
(1):获取配置的所有的切面增强方法
(2):找到所有的增强方法中能应用到当前bean方法中的
(3):获取到能在当前bean使用的增强方法的集合,并按照一定规则排序
(4):如果能在当前bean使用的增强方法的集合不为空,则转为数组返回,否则返回null
2):如果返回的数组不为空,则需要代理
(1):将bean的name作为key,值为true,放在advisedBeans(所有增强过的bean的ConcurrentHashMap)中
(2):创建代理对象,Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
①:如果能在当前bean使用的增强方法
②:遍历将其添加到proxyFactory中
③: DefaultAopProxyFactory中创建代理对象,如果目标类实现了接口,则使用JDK动态代理;否则使用CGlib动态代理
JdkDynamicAopProxy(AdvisedSupport config)
ObjenesisCglibAopProxy(AdvisedSupport config)
(3):将bean作为key,代理对象的class对象作为value,保存到private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<Object, Class<?>>(16);中
(4):返回代理对象(代理对象中包含了增强器和目标对象等)
(5):以后在容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行增强方法的流程
3)否则不需要代理,将bean的name作为key,值为false,放在advisedBeans中,表示不需要增强
总结:AnnotationAwareAspectJAutoProxyCreator在初始化后置方法postProcessAfterInitialization中,判断是否有增强方法能应用到当前bean中,若有,则为当前bean创建代理对象,并保存到Spring容器中,以后从Spring容器中获取到的就是代理对象。
从容器中获取的对象是代理对象,即容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细的信息(比如要应用的切面中的增强方法,也叫增强器,目标对象等)
执行目标对象Target中的切入点方法,即执行被增强的方法的流程:
F7进入切点方法:
1、CglibAopProxy.intercept(); 拦截目标方法的执行
2、获取目标对象
Object target = null; // 目标对象
TargetSource targetSource = this.advised.getTargetSource();
target = targetSource.getTarget();
3、根据ProxyFactory对象获取将要执行的目标方法拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice // 实际逻辑代码
1):List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
保存所有的拦截器,包括一个默认的 ExposeInvocationInterceptor.ADVISOR 和 其他所有切点方法的增强器
2):遍历所有的增强器,将其转为MethodInterceptor 【MethodInterceptor[] interceptors = registry.getInterceptors(advisor);】
如果增强器是MethodInterceptor,直接放入List<MethodInterceptor>集合中
如果不是,使用AdvisorAdapter将增强器转为MethodInterceptor,然后再放入List<MethodInterceptor>集合中
最后将集合转为数组返回
4、如果没有拦截器链,则直接执行目标方法(拦截器链,每一个通知方法又被包装为方法拦截器,利用MethodInterceptor机制)
5、如果有拦截器链,把需要执行的目标对象,目标方法,拦截器等信息作为参数创建一个CglibMethodInvocation对象并调用其proceed()方法
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
CglibMethodInvocation对象:
拦截器列表:
6、拦截器的触发过程
1):如果没有拦截器执行目标方法,或者拦截器的索引和拦截器数组-1大小一样(即执行到了最后一个拦截器),则执行目标方法
2):链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回后再去执行(类似于递归调用),
如上面拦截器的调用顺序是 Expose-->AfterReturning-->Around-->Before,然后前面的等待后面的返回再执行,最后实际执行顺序是Before-->Around-->AfterReturning-->Expose
拦截器链的机制,保证通知方法与目标方法的执行顺序。
AOP总结
1、@EnableAspectJAutoProxy 开启AOP功能
2、@EnableAspectJAutoProxy 会给容器中注册一个组件 AnnotationAwareApectJAutoProxyCreator
3、AnnotationAwareApectJAutoProxyCreator是一个后置处理器
4、容器的创建流程
1):registerBeanPostProcessors(beanFactory); 注册后置处理器,创建AnnotationAwareApectJAutoProxyCreator对象
2):finishBeanFactoryInitialization(beanFactory); 初始化剩下的单实例bean
(1):创建业务逻辑组件和切面组件
(2):AnnotationAwareApectJAutoProxyCreator 拦截组件的创建过程
(3): 组件创建完成之后,作为后置处理器的AnnotationAwareApectJAutoProxyCreator在postProcessAfterInitialization方法中判断组件是否需要增强,如果需要则 将需要应用到目标对象的切面中的通知方法,包装成增强器Advisor,然后给业务逻辑组件创建一个代理对象。
5、执行目标方法
1):代理对象来执行目标方法
2):CglibAopProxy.intercept(); 拦截目标方法的执行
(1):得到目标方法执行的拦截器链
(2):利用拦截器的链式机制,依次进入每一个拦截器进行执行
(3):实际执行顺序:
正常执行:前置通知-->目标方法-->后置通知-->返回通知
出现异常:前置通知-->目标方法-->后置通知-->异常通知
二、事务
声明式事务
jdbc和tx依赖:
<!--jdbc & tx--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
数据源和mysql连接依赖:
<!--dbcp datasource--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-dbcp2</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency>
配置文件信息:
/** * @EnableTransactionManagement 开启基于注解的事务管理功能 * 1、配置数据源 * 2、配置事务管理器来管理事务 * 3、给方法上标注 @Transactional 表示当前方法是一个事务方法,@Transaction默认回滚Error和RuntimeException,但是不包括和RuntimeException * 一样同属于Exception子类的如IOException、SQLException和自定义异常等,对于这些异常如果也要回滚要在rollbackFor中指定 */ @EnableTransactionManagement @Configuration @ComponentScan(value = {"com.yang.service"}) public class TransactionConfig { @Bean public DataSource myDataSource() { BasicDataSource dataSource = new BasicDataSource(); dataSource.setUsername("yang"); dataSource.setPassword("yang"); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/test"); return dataSource; } /** * 如果bean之间有依赖,直接放进参数中即可,参数值会从Spring容器中取,然后赋值 * 参数从Spring容器中取 * * @param myDataSource * @return */ @Bean public JdbcTemplate jdbcTemplate(DataSource myDataSource) { JdbcTemplate jdbcTemplate = new JdbcTemplate(myDataSource); // 也可以直接调用,Spring对@Configuration类会特殊处理;给容器中加组件的方法,多次调用都只是从容器中找组件 // JdbcTemplate jdbcTemplate = new JdbcTemplate(myDataSource()); return jdbcTemplate; } /** * 注册事务管理器在容器中 * * @return * @throws Exception */ @Bean public PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(myDataSource()); } }
@EnableTransactionManagement 做了什么?
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(TransactionManagementConfigurationSelector.class) public @interface EnableTransactionManagement { boolean proxyTargetClass() default false; AdviceMode mode() default AdviceMode.PROXY; int order() default Ordered.LOWEST_PRECEDENCE; }
1、导入了TransactionManagementConfigurationSelector,TransactionManagementConfigurationSelector往容器中导入了两个组件
AutoProxyRegistrar 、ProxyTransactionManagementConfiguration
/** * Returns {@link ProxyTransactionManagementConfiguration} or * {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY} * and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()}, * respectively. */ @Override protected String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { case PROXY: return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: return new String[] {determineTransactionAspectClass()}; default: return null; } } private String determineTransactionAspectClass() { return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ? TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME : TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME); } // public static final String JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME = "org.springframework.transaction.aspectj.AspectJJtaTransactionManagementConfiguration"; // public static final String TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME = "org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration";
(1)、AutoProxyRegistrar
给容器中注册了一个beanNameorg.springframework.aop.config.internalAutoProxyCreator,类型为InfrastructureAdvisorAutoProxyCreator的组件(bean),其是一个后置处理器,和AOP中的AnnotationAwareAspectJAutoProxyCreator类似,它们beanName相同。都是在对象创建完成之后利用后置处理器的初始化后置方法,包装对象,然后返回一个包含增强器的代理对象,代理对象执行方法利用拦截器链进行调用。
(2)、ProxyTransactionManagementConfiguration是一个配置文件类
/** * {@code @Configuration} class that registers the Spring infrastructure beans * necessary to enable proxy-based annotation-driven transaction management. * * @author Chris Beams * @since 3.1 * @see EnableTransactionManagement * @see TransactionManagementConfigurationSelector */ @Configuration public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { // 事务增强器 BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); advisor.setTransactionAttributeSource(transactionAttributeSource()); advisor.setAdvice(transactionInterceptor()); if (this.enableTx != null) { advisor.setOrder(this.enableTx.<Integer>getNumber("order")); } return advisor; } @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionAttributeSource transactionAttributeSource() { return new AnnotationTransactionAttributeSource(); } @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionInterceptor transactionInterceptor() { // 事务拦截器 TransactionInterceptor interceptor = new TransactionInterceptor(); interceptor.setTransactionAttributeSource(transactionAttributeSource()); if (this.txManager != null) { interceptor.setTransactionManager(this.txManager); } return interceptor; } }
1、往容器中注册事务增强器transactionAdvisor,其中事务增强器中又依赖了:
1):事务增强器要用事务注解的参数信息,TransactionAttributeSource,AnnotationTransactionAttributeSource来解析事务注解
2):事务拦截器:TransactionInterceptor,保存了事务属性信息,事务管理器。其实现了MethodInterceptor接口。在目标方法执行的时候:执行拦截器链,然后执行事务拦截器:
(1):先获取事务相关的属性
(2):再获取PlatformTransactionManager事务管理器,如果在@Transactional注解中没有指定transactionManager,则最终会从容器中按照类型获取一个PlatformTransactionManager
(3):执行目标方法
如果异常,获取到事务管理器,利用事务管理回滚操作
【transactionInfo.getTransactionManager().rollback(txInfo.getTransactionStatus())】
如果正常,利用事务管理器,提交事务【transactionInfo.getTransactionManager().commit(txInfo.getTransactionStatus());】
TransactionInterceptor#invoke
@Override @Nullable public Object invoke(MethodInvocation invocation) throws Throwable { // Work out the target class: may be {@code null}. // The TransactionAttributeSource should be passed the target class // as well as the method, which may be from an interface. Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // Adapt to TransactionAspectSupport's invokeWithinTransaction... return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); }
@Transactional注解处理器的核心代码,TransactionAspectSupport#invokeWithinTransaction:278,从TransactionInterceptor#invoke进入:
/** * General delegate for around-advice-based subclasses, delegating to several other template * methods on this class. Able to handle {@link CallbackPreferringPlatformTransactionManager} * as well as regular {@link PlatformTransactionManager} implementations. * @param method the Method being invoked * @param targetClass the target class that we're invoking the method on * @param invocation the callback to use for proceeding with the target invocation * @return the return value of the method, if any * @throws Throwable propagated from the target invocation */ @Nullable protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation) throws Throwable { // If the transaction attribute is null, the method is non-transactional. TransactionAttributeSource tas = getTransactionAttributeSource(); final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null); final PlatformTransactionManager tm = determineTransactionManager(txAttr); // 确定要用于给定交易的特定交易管理器 final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); // 开启事务 Object retVal = null; try { // This is an around advice: Invoke the next interceptor in the chain. // This will normally result in a target object being invoked. retVal = invocation.proceedWithInvocation(); // 执行业务方法 } catch (Throwable ex) { // target invocation exception completeTransactionAfterThrowing(txInfo, ex); // 回滚事务 throw ex; // 仍往上抛出异常,供上层捕获 } finally { cleanupTransactionInfo(txInfo); // Reset the TransactionInfo ThreadLocal. } commitTransactionAfterReturning(txInfo); // 提交事务 return retVal; } else { ... } }
回滚事务:
/** * Handle a throwable, completing the transaction. * We may commit or roll back, depending on the configuration. * @param txInfo information about the current transaction * @param ex throwable encountered */ protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) { if (txInfo != null && txInfo.getTransactionStatus() != null) { if (logger.isTraceEnabled()) { logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "] after exception: " + ex); } if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) { try { txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus()); } catch (TransactionSystemException ex2) { logger.error("Application exception overridden by rollback exception", ex); ex2.initApplicationException(ex); throw ex2; } catch (RuntimeException | Error ex2) { logger.error("Application exception overridden by rollback exception", ex); throw ex2; } } else { // We don't roll back on this exception. // Will still roll back if TransactionStatus.isRollbackOnly() is true. // 默认回滚(ex instanceof RuntimeException || ex instanceof Error) 异常,其他异常不会回滚,仍提交事务 try { txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); } catch (TransactionSystemException ex2) { logger.error("Application exception overridden by commit exception", ex); ex2.initApplicationException(ex); throw ex2; } catch (RuntimeException | Error ex2) { logger.error("Application exception overridden by commit exception", ex); throw ex2; } } } }
最终回滚代码为:DataSourceTransactionManager#doRollback
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); con.rollback();
提交事务:
/** * Execute after successful completion of call, but not after an exception was handled. * Do nothing if we didn't create a transaction. * @param txInfo information about the current transaction */ protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) { if (txInfo != null && txInfo.getTransactionStatus() != null) { if (logger.isTraceEnabled()) { logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]"); } txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); // 提交事务 } }
最终提交代码为:
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); con.commit();
END.