六Spring事务--5声明式事务的核心类
六Spring事务--5声明式事务的核心类
6.3 实现声明式事务注解的核心类
事务的配置核心类,主要是实现@EnableTransactionManagement(@EnableXXXXXX等功能)核心的类。这些类用来注册相关的bean。
6.3.1 @EnableTransactionManagement的原理
@EnableTransactionManagement声明在主配置类上,表示开启声明式事务,其原理是通过@Import导入TransactionManagementConfigurationSelector组件,该组件通过selectImport方法,根据返回的字符串集合,决定向spring的beanFactory中导入组件AutoProxyRegistrar和ProxyTransactionManagementConfiguration;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//导入selector类
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
//注解参数,标识是否代理targetclass
boolean proxyTargetClass() default false;
//增强模式
AdviceMode mode() default AdviceMode.PROXY;
//order顺序
int order() default Ordered.LOWEST_PRECEDENCE;
}
@EnableTransactionManagement注解用@Import导入TransactionManagementConfigurationSelector类
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
//返回AutoProxyRegistrar和ProxyTransactionManagementConfiguration的类名的字符串数组
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);
}
}
这里,通过selectImports方法,获取类名的字符串数组,这里,会向spring导入两个组件类AutoProxyRegistrar和ProxyTransactionManagementConfiguration(@configuration注解的配置类)
selector继承结构如上。
6.3.2 ImportSelector
public interface ImportSelector {
/**
* parm:importingClassMetadata 是@import所注解的类的元数据,如上面EnableTransactionManagement的元数据
*/
//选择并返回需要导入spring的类的名称,基于AnnotationMetadata,并且导入@configuration注解中,导入spring容器
String[] selectImports(AnnotationMetadata importingClassMetadata);
}
这个方法返回字符串数组,当在配置类中被@import引入,返回的字符串数组中的类名会被spring容器创建。
使用用途:
动态加载特定的类:通过该类,可以做一个类似开关的注解类,通过注解,可以向spring容器中添加selectImports返回的字符串对应的类。
用法:
首先创建实现ImportSelector的类,然后通过@import(selector)添加在配置类@configuration上。然后spring就会把方法返回的字符串,new出对象然后添加入spring的beanFactory中。
public class Dynamic {
public void say(){
System.out.println("log for Dynamic");
return Proxy.newProxyInstance(StaticClassB);//伪码
}
}
//自定义selector,然后可以自行把dynamic类装载入spring容器
public class MyImportSelect implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{Dynamic.class.getName()};
}
}
//构造自建的@EnableXXX类,作为开关,可以动态添加selector内的类
@Retention(RetentionPolicy.RUNTIME) //开启运行时加载
@Import(MyImportSelect.class)
public @interface EnableMySelector {
}
//配置类上添加@enable注解,动态添加类
@ComponentScan("com.demo")
@EnableMySelector
public class AppConfig { }
public class Test {
public static void main(String[] args) {
//从配置类创建spring容器
AnnotationConfigApplicationContext anno=newAnnotationConfigApplicationContext(AppConfig.class);
anno.getBean(Dynamic.class).say();
}
}
运行打印
log for Dynamic
6.3.2.1 ImportSelector实现原理
ImportSelector类内方法selectImports返回的字符串数组,会在ConfigurationClassParser中被解析,并最终实例化为bean。(parser原理,详细看[2.18 spring.handlers解析标签的原理](#2.18 spring.handlers解析标签的原理))
//parse()方法中调用,省略不看
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
boolean checkForCircularImports) {
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
//import导入的类
for (SourceClass candidate : importCandidates) {
/**----------------------------------处理ImportSelector的情况-------------------------------------*/
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
//实例化当前candidateClass上的ImportSelector类
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
//DeferredImportSelector情况处理(后来很少用到)
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
//ImportSelector情况的处理
else {
//调用selectImports方法,得到自定义方法返回需要实例化的类名称
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
/**…………………………………………………………递归调用,处理 selectImports导入的类,也是注册类的情况…………………………………………………………*/
//获取selectImports内返回的实例类,对于spring事务,就是AutoProxyRegistrar(对应于下面ImportBeanDefinitionRegistrar的处理逻辑)和ProxyTransactionManagementConfiguration(对应于下面configuration类的处理逻辑)
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
//递归调用processImports
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
}
/**-----------------------处理ImportBeanDefinitionRegistrar情况---------------------------------*/
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
//实例化为ImportBeanDefinitionRegistrar类
ImportBeanDefinitionRegistrar registrar =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry);
//添加ImportBeanDefinitionRegistrar到本地缓存
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
/**-----------------------处理为普通@Configuration注解的类的情况---------------------------------*/
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
//处理配置类configuration的情况
processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
finally {
this.importStack.pop();
}
}
}
spring事务中selectImport方法,返回AutoProxyRegistrar(对应于下面ImportBeanDefinitionRegistrar的处理逻辑)和ProxyTransactionManagementConfiguration(对应于下面configuration类的处理逻辑)两个组件类,在parser中,首先实例化selector,然后对selector.selectImports方法返回的对象,利用递归的调用,再处理registrar和configuration的配置类,向spring中注册对象。
6.3.3 ImportBeanDefinitionRegistrar
这里的作用,跟ImportSelector功能相似,但是更强大。
public interface ImportBeanDefinitionRegistrar {
/**importingClassMetadata 是@import所注解的类的元数据
BeanDefinitionRegistry 是spring的注册器*/
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
BeanNameGenerator importBeanNameGenerator) {
//内部调用
registerBeanDefinitions(importingClassMetadata, registry);
}
//通过registry向容器中注册beandefinition对象
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
}
}
6.3.3.1 AutoProxyRegistrar---spring事务注册类
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
private final Log logger = LogFactory.getLog(getClass());
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
//
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (candidate == null) {
continue;
}
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
//默认的proxy模式
if (mode == AdviceMode.PROXY) {
//注册autoProxyCreator类
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
}
}
AopConfigUtils{
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
//向spring注册InfrastructureAdvisorAutoProxyCreator类
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
AutoProxyRegistrar类向spring注册事务的自动代理创建类InfrastructureAdvisorAutoProxyCreator。
6.3.4 InfrastructureAdvisorAutoProxyCreator

InfrastructureAdvisorAutoProxyCreator类同AOP中核心组件相同,实现后置处理器类,会在spring对象实例化、初始化前后,自动创建当前类的代理类。详见AOP中autoproxycreator类。
public class InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
@Nullable
private ConfigurableListableBeanFactory beanFactory;
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.initBeanFactory(beanFactory);
this.beanFactory = beanFactory;
}
//判断是否是符合条件的AdvisorBean
@Override
protected boolean isEligibleAdvisorBean(String beanName) {
//bean的role为BeanDefinition.ROLE_INFRASTRUCTURE
return (this.beanFactory != null && this.beanFactory.containsBeanDefinition(beanName) &&
this.beanFactory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE);
}
}
InfrastructureAdvisorAutoProxyCreator提供isEligibleAdvisorBean(String beanName)方法判断当前beanname是否是符合条件的AdvisorBean,而只有ProxyTransactionManagementConfiguration配置类创建的advisor、advice和AnnotationTransactionAttributeSource为BeanDefinition.ROLE_INFRASTRUCTURE。
因此该逻辑主要是筛查出这三个实例。
6.3.5 ProxyTransactionManagementConfiguration
该类是spring事务的重要配置类,用来自动创建事务所需要的advisor等重要组件类。
//配置类
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
/**…………………………………………………………………………………………………创建spring事务的advisor类……………………………………………………………………………………*/
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
//创建advisor类
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
//设置属性源source
advisor.setTransactionAttributeSource(transactionAttributeSource);
//设置advice增强
advisor.setAdvice(transactionInterceptor);
if (this.enableTx != null) {
//如果有顺序属性,设置优先级
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
/**…………………………………………………………创建spring事务的AnnotationTransactionAttributeSource类…………………………………………………*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
///该类用来解析@Transactional注解上的事务属性
return new AnnotationTransactionAttributeSource();
}
/**…………………………………………………………………………………………………创建spring事务的advice类……………………………………………………………………………………*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
//设置事务属性源
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
//设置事务管理器
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
配置类,创建spring事务所需要的advisor、advice和AnnotationTransactionAttributeSource(用来解析@Transactional上的事务属性)。
注意:
这个配置类内创建的三个实例,bean的role为BeanDefinition.ROLE_INFRASTRUCTURE。
6.3.6 @EnableXXX原理
@enableXXX注解,通过@Import(),作为开关功能的注解,开启XXX功能,可以通过ImportSelector、ImportBeanDefinitionRegistrar、Configuration类,向spring容器中动态添加注册相关的重要组件类,实现自动开关功能。