对SpringBoot
有多了解,其实就是看你对Spring Framework
有多熟悉~ 好比SpringBoot
大量的模块装配的设计模式,其实它属于Spring Framework提供的能力。SpringBoot大行其道的今天,基于XML
配置的Spring Framework的使用方式注定已成为过去式。注解驱动应用,面向元数据编程已然成受到愈来愈多开发者的偏好了,毕竟它的便捷程度、优点都是XML方式不可比拟的。java
@Configuration @ConditionalOnClass({PlatformTransactionManager.class}) @AutoConfigureAfter({JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class}) @EnableConfigurationProperties({TransactionProperties.class}) public class TransactionAutoConfiguration { public TransactionAutoConfiguration() { } @Bean @ConditionalOnMissingBean public TransactionManagerCustomizers platformTransactionManagerCustomizers(ObjectProvider<PlatformTransactionManagerCustomizer<?>> customizers) { return new TransactionManagerCustomizers((Collection)customizers.orderedStream().collect(Collectors.toList())); } @Configuration @ConditionalOnBean({PlatformTransactionManager.class}) @ConditionalOnMissingBean({AbstractTransactionManagementConfiguration.class}) public static class EnableTransactionManagementConfiguration { public EnableTransactionManagementConfiguration() { } @Configuration @EnableTransactionManagement( proxyTargetClass = true ) @ConditionalOnProperty( prefix = "spring.aop", name = {"proxy-target-class"}, havingValue = "true", matchIfMissing = true ) //默认采用cglib代理 public static class CglibAutoProxyConfiguration { public CglibAutoProxyConfiguration() { } } @Configuration @EnableTransactionManagement( proxyTargetClass = false ) @ConditionalOnProperty( prefix = "spring.aop", name = {"proxy-target-class"}, havingValue = "false", matchIfMissing = false ) public static class JdkDynamicAutoProxyConfiguration { public JdkDynamicAutoProxyConfiguration() { } } } @Configuration //当PlatformTransactionManager类型的bean存在而且当存在多个bean时指定为Primary的 PlatformTransactionManager存在时,该配置类才进行解析 @ConditionalOnSingleCandidate(PlatformTransactionManager.class) public static class TransactionTemplateConfiguration { private final PlatformTransactionManager transactionManager; public TransactionTemplateConfiguration(PlatformTransactionManager transactionManager) { this.transactionManager = transactionManager; } // 因为TransactionAutoConfiguration是在DataSourceTransactionManagerAutoConfiguration以后才被解析处理的,而在DataSourceTransactionManagerAutoConfiguration中配置了transactionManager,所以, TransactionTemplateConfiguration 会被处理. @Bean @ConditionalOnMissingBean public TransactionTemplate transactionTemplate() { return new TransactionTemplate(this.transactionManager); } } }
提示:使用@EnableTransactionManagement
注解前,请务必保证你已经配置了至少一个PlatformTransactionManager
的Bean,不然会报错。(固然你也能够实现TransactionManagementConfigurer
来提供一个专属的,只是咱们通常都不这么去作~~~)spring
@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 2147483647; }
简直和@EnableAsync
注解的如出一辙。不一样之处只在于@Import
导入器导入的这个类.编程
对比一下设计模式
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AsyncConfigurationSelector.class) public @interface EnableAsync { // 支持自定义注解类型 去支持异步~~~ Class<? extends Annotation> annotation() default Annotation.class; boolean proxyTargetClass() default false; AdviceMode mode() default AdviceMode.PROXY; int order() default Ordered.LOWEST_PRECEDENCE; }
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> { public TransactionManagementConfigurationSelector() { } protected String[] selectImports(AdviceMode adviceMode) { switch(adviceMode) { case PROXY: return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: return new String[]{this.determineTransactionAspectClass()}; default: return null; } } private String determineTransactionAspectClass() { return ClassUtils.isPresent("javax.transaction.Transactional", this.getClass().getClassLoader()) ? "org.springframework.transaction.aspectj.AspectJJtaTransactionManagementConfiguration" : "org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration"; } }
依然能够看出和@EnableAsync
导入的AsyncConfigurationSelector
一模一样,都继承自AdviceModeImportSelector
,毕竟模式同样,举一反三,一通百通~缓存
AdviceModeImportSelector
目前所知的三个子类是:AsyncConfigurationSelector
、TransactionManagementConfigurationSelector
、CachingConfigurationSelector
。因而可知后面还会着重分析的Spring
的缓存体系@EnableCaching
,模式也是和这个极其相似的~~~异步
它是个ImportBeanDefinitionRegistrar
,能够实现本身向容器里注册Bean的定义信息ide
// @since 3.1 public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar { private final Log logger = LogFactory.getLog(this.getClass()); public AutoProxyRegistrar() { } public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean candidateFound = false; // 这里面须要特别注意的是:这里是拿到全部的注解类型~~~而不是只拿@EnableAspectJAutoProxy这个类型的 // 缘由:由于mode、proxyTargetClass等属性会直接影响到代理得方式,而拥有这些属性的注解至少有: // @EnableTransactionManagement、@EnableAsync、@EnableCaching等~~~~ // 甚至还有启用AOP的注解:@EnableAspectJAutoProxy它也能设置`proxyTargetClass`这个属性的值,所以也会产生关联影响~ Set<String> annTypes = importingClassMetadata.getAnnotationTypes(); Iterator var5 = annTypes.iterator(); while(var5.hasNext()) { String annType = (String)var5.next(); AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType); if (candidate != null) { Object mode = candidate.get("mode"); Object proxyTargetClass = candidate.get("proxyTargetClass"); // 若是存在mode且存在proxyTargetClass 属性 // 而且两个属性的class类型也是对的,才会进来此处(所以其他注解至关于都挡外面了~) if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) { candidateFound = true; if (mode == AdviceMode.PROXY) { // 它主要是注册了一个`internalAutoProxyCreator`,可是若出现屡次的话,这里不是覆盖的形式,而是以优先级的形式 AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry); //看要不要强制使用CGLIB的方式(由此能够发现 这个属性若出现屡次,是会是覆盖的形式) if ((Boolean)proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); return; } } } } } if (!candidateFound && this.logger.isInfoEnabled()) { String name = this.getClass().getSimpleName(); this.logger.info(String.format("%s was imported but no annotations were found having both 'mode' and 'proxyTargetClass' attributes of type AdviceMode and boolean respectively. This means that auto proxy creator registration and configuration may not have occurred as intended, and components may not be proxied as expected. Check to ensure that %s has been @Import'ed on the same class where these annotations are declared; otherwise remove the import of %s altogether.", name, name, name)); } } }
跟踪AopConfigUtils
的源码你会发现,事务这块向容器注入的是一个InfrastructureAdvisorAutoProxyCreator
,而且看看是采用CGLIB
仍是JDK
代理。它主要是读取Advisor
类,并对符合的bean进行二次代理。ui
@Configuration public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { public ProxyTransactionManagementConfiguration() { } @Bean( name = {"org.springframework.transaction.config.internalTransactionAdvisor"} ) @Role(2) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); advisor.setTransactionAttributeSource(this.transactionAttributeSource()); advisor.setAdvice(this.transactionInterceptor()); if (this.enableTx != null) { // 顺序由@EnableTransactionManagement注解的Order属性来指定 默认值为:Ordered.LOWEST_PRECEDENCE advisor.setOrder((Integer)this.enableTx.getNumber("order")); } return advisor; } @Bean @Role(2) // TransactionAttributeSource 这种类特别像 `TargetSource`这种类的设计模式 public TransactionAttributeSource transactionAttributeSource() { return new AnnotationTransactionAttributeSource(); } @Bean @Role(2) // 事务拦截器,它是个`MethodInterceptor`,它也是Spring处理事务最为核心的部分 // 请注意:你能够本身定义一个TransactionInterceptor(同名的),来覆盖此Bean public TransactionInterceptor transactionInterceptor() { TransactionInterceptor interceptor = new TransactionInterceptor(); interceptor.setTransactionAttributeSource(this.transactionAttributeSource()); if (this.txManager != null) { interceptor.setTransactionManager(this.txManager); } return interceptor; } }
@Configuration public abstract class AbstractTransactionManagementConfiguration implements ImportAware { @Nullable protected AnnotationAttributes enableTx; // 此处:注解的默认的事务处理器(可议经过实现接口TransactionManagementConfigurer来自定义配置) // 由于事务管理器这个东西,通常来讲全局一个就行,可是Spring也提供了定制化的能力~~~ @Nullable protected PlatformTransactionManager txManager; public AbstractTransactionManagementConfiguration() { } public void setImportMetadata(AnnotationMetadata importMetadata) { this.enableTx = AnnotationAttributes.fromMap(importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false)); //这个注解@EnableTransactionManagement是必须的~~~~~~~~~~~~~~~~不然报错了 if (this.enableTx == null) { throw new IllegalArgumentException("@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName()); } } @Autowired( required = false ) // 这里和@Async的处理同样,配置文件能够实现这个接口。而后给注解驱动的给一个默认的事务管理器~~~~ void setConfigurers(Collection<TransactionManagementConfigurer> configurers) { if (!CollectionUtils.isEmpty(configurers)) { // 一样的,最多也只容许你去配置一个~~~ if (configurers.size() > 1) { throw new IllegalStateException("Only one TransactionManagementConfigurer may exist"); } else { TransactionManagementConfigurer configurer = (TransactionManagementConfigurer)configurers.iterator().next(); this.txManager = configurer.annotationDrivenTransactionManager(); } } } @Bean( name = {"org.springframework.transaction.config.internalTransactionalEventListenerFactory"} ) @Role(2) public static TransactionalEventListenerFactory transactionalEventListenerFactory() { return new TransactionalEventListenerFactory(); } }
这个就是事务的匹配Pointcut
切面,决定了哪些类须要生成代理对象从而应用事务。this
// 首先它的访问权限事default 显示是给内部使用的 // 首先它继承自StaticMethodMatcherPointcut 因此`ClassFilter classFilter = ClassFilter.TRUE;` 匹配全部的类 // 而且isRuntime=false 表示只须要对方法进行静态匹配便可~~~~ abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable { // 方法的匹配 静态匹配便可(由于事务无须要动态匹配这么细粒度~~~) @Override public boolean matches(Method method, Class<?> targetClass) { // 实现了以下三个接口的子类,就不须要被代理了 直接放行 // TransactionalProxy它是SpringProxy的子类。 若是是被TransactionProxyFactoryBean生产出来的Bean,就会自动实现此接口,那么就不会被这里再次代理了 // PlatformTransactionManager:spring抽象的事务管理器~~~ // PersistenceExceptionTranslator对RuntimeException转换成DataAccessException的转换接口 if (TransactionalProxy.class.isAssignableFrom(targetClass) || PlatformTransactionManager.class.isAssignableFrom(targetClass) || PersistenceExceptionTranslator.class.isAssignableFrom(targetClass)) { return false; } // 重要:拿到事务属性源~~~~~~ // 若是tas == null表示没有配置事务属性源,那是所有匹配的 也就是说全部的方法都匹配~~~~(这个处理仍是比较让我诧异的~~~) // 或者 标注了@Transaction这样的注解的方法才会给与匹配~~~ TransactionAttributeSource tas = getTransactionAttributeSource(); return (tas == null || tas.getTransactionAttribute(method, targetClass) != null); } ... // 由子类提供给我,告诉事务属性源~~~ @Nullable protected abstract TransactionAttributeSource getTransactionAttributeSource(); }
这个事务注解能够用在类上,也能够用在方法上。spa
注意 : 若是某个方法和该方法所属类上都有事务注解属性,优先使用方法上的事务注解属性。
另外,Spring 支持三个不一样的事务注解 :
org.springframework.transaction.annotation.Transactional
@Configuration @EnableTransactionManagement public class MyTransactionManagementConfigurer implements TransactionManagementConfigurer { @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(dataSource); return dataSourceTransactionManager; } @Override public PlatformTransactionManager annotationDrivenTransactionManager() { return null; } }
@EnableAspectJAutoProxy
会像容器注入AnnotationAwareAspectJAutoProxyCreator
@EnableTransactionManagement
会像容器注入InfrastructureAdvisorAutoProxyCreator
public abstract class AopConfigUtils { ... @Nullable private static BeanDefinition registerOrEscalateApcAsRequired( Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) { // 能够发现这里有一个很巧妙的处理:会对自动代理建立器进行升级~~~~ // 因此若是你第一次进来的是`InfrastructureAdvisorAutoProxyCreator`,第二次进来的是`AnnotationAwareAspectJAutoProxyCreator`,那就会取第二次进来的这个Class // 反之则不行。这里面是维护的一个优先级顺序的,具体参看本类的static代码块,就是顺序 最后一个`AnnotationAwareAspectJAutoProxyCreator`才是最为强大的 if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); if (!cls.getName().equals(apcDefinition.getBeanClassName())) { int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } return null; } RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; } ... }
从上面的分析能够知道:不管你的这些注解有多少个,不管他们的前后顺序如何,它内部都有咯优先级提高的机制来保证向下的覆盖兼容。所以通常状况下,咱们使用的都是最高级的AnnotationAwareAspectJAutoProxyCreator
这个自动代理建立器~~~