熟悉Spring Bean 生命周期
了解Spring Aop原理
总结Spring Aop
引入spring tx模块
org.springframework spring-tx
学习完spring aop知识。我们可以知道他是使用 beanPostProcessor接口postProcessAfterInitialization 方法处理。“如果切面拦截这个类的方法,那么将创建代理”
查找可能的切面
protected List findCandidateAdvisors() {Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");return this.advisorRetrievalHelper.findAdvisorBeans();}
public List findAdvisorBeans() {// Determine list of advisor bean names, if not cached already.String[] advisorNames = this.cachedAdvisorBeanNames;if (advisorNames == null) {// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the auto-proxy creator apply to them!advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);this.cachedAdvisorBeanNames = advisorNames;}List advisors = new ArrayList<>();for (String name : advisorNames) {if (isEligibleBean(name)) {if (this.beanFactory.isCurrentlyInCreation(name)) {if (logger.isTraceEnabled()) {logger.trace("Skipping currently created advisor '" + name + "'");}}else { advisors.add(this.beanFactory.getBean(name, Advisor.class)); }}}return advisors;}
查找ioc容器中类型是Advisor.class的BeanDefinition。并且我们期望bean来自spring-tx模块下。
于是我们发现目标类 BeanFactoryTransactionAttributeSourceAdvisor
BeanFactoryTransactionAttributeSourceAdvisor何时注册到ioc容器呢?
我们全局搜索下BeanFactoryTransactionAttributeSourceAdvisor
发现如下类:
EnableTransactionManagement 是个注解,importTransactionManagementConfigurationSelector
TransactionManagementConfigurationSelector 实现了ImportSelector接口将执行selectImports方法。注册ProxyTransactionManagementConfiguration到ioc容器
ProxyTransactionManagementConfiguration 以编程方式 @Bean注册 BeanFactoryTransactionAttributeSourceAdvisor。
为什么Springboot 没有标记EnableTransactionManagement注解。事务仍然生效了呢?
答:Springboot开启了自动装配。TransactionAutoConfiguration 标记了EnableTransactionManagement注解。
@Configuration(proxyBeanMethods = false)@ConditionalOnBean(TransactionManager.class)@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)public static class EnableTransactionManagementConfiguration {@Configuration(proxyBeanMethods = false)@EnableTransactionManagement(proxyTargetClass = false)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")public static class JdkDynamicAutoProxyConfiguration {}@Configuration(proxyBeanMethods = false)@EnableTransactionManagement(proxyTargetClass = true)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",matchIfMissing = true)public static class CglibAutoProxyConfiguration {}
依类图可知:
TransactionInterceptor 实现了Advice接口。 并注入到BeanFactoryTransactionAttributeSourceAdvisor。
TransactionAttributeSourcePointcut实现了Point接口,并注入到BeanFactoryTransactionAttributeSourceAdvisor。
并且继承了StaticMethodMatcherPointcut 抽象类。而StaticMethodMatcherPointcut.getMethodMatcher方法返回是其自己。
AnnotationTransactionAttributeSource注入到TransactionAttributeSourcePointcut。
该配置类将AnnotationTransactionAtrributeSource和TransactionInterceptor 注入到BeanFactoryTransactionAttributeSourceAdvisor。
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();advisor.setTransactionAttributeSource(transactionAttributeSource);advisor.setAdvice(transactionInterceptor);if (this.enableTx != null) {advisor.setOrder(this.enableTx.getNumber("order"));}return advisor;}@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionAttributeSource transactionAttributeSource() {return new AnnotationTransactionAttributeSource();}@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;}}
检查BeanDefinition是否被切面拦截
检查目标类是否有被切面拦截!核心是取Advisor.pointCut是否拦截bd的方法。
public static List findAdvisorsThatCanApply(List candidateAdvisors, Class> clazz) {List eligibleAdvisors = new ArrayList<>();boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {if (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;}public static boolean canApply(Advisor advisor, Class> targetClass, boolean hasIntroductions) {if (advisor instanceof PointcutAdvisor) {PointcutAdvisor pca = (PointcutAdvisor) advisor;return canApply(pca.getPointcut(), targetClass, hasIntroductions);}}
public static boolean canApply(Pointcut pc, Class> targetClass, boolean hasIntroductions) {if (!pc.getClassFilter().matches(targetClass)) {return false;}MethodMatcher methodMatcher = pc.getMethodMatcher();if (methodMatcher == MethodMatcher.TRUE) {// No need to iterate the methods if we're matching any method anyway...return true;}IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;if (methodMatcher instanceof IntroductionAwareMethodMatcher) {introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;}Set> classes = new LinkedHashSet<>();if (!Proxy.isProxyClass(targetClass)) {classes.add(ClassUtils.getUserClass(targetClass));}classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));for (Class> clazz : classes) {Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);for (Method method : methods) {if (introductionAwareMethodMatcher != null ?introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :methodMatcher.matches(method, targetClass)) {return true;}}}return false;}
重点在这个Pointcut对象
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {@Override@Nullableprotected TransactionAttributeSource getTransactionAttributeSource() {return transactionAttributeSource;}};@Overridepublic Pointcut getPointcut() {return this.pointcut;}/*** Set the {@link ClassFilter} to use for this pointcut.* Default is {@link ClassFilter#TRUE}.*/public void setClassFilter(ClassFilter classFilter) {this.pointcut.setClassFilter(classFilter);}
BeanFactoryTransactionAttributeSourceAdvisor的pointcut 字段实现类是TransactionAttributeSourcePointcut。
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {protected TransactionAttributeSourcePointcut() {setClassFilter(new TransactionAttributeSourceClassFilter());}/*** {@link ClassFilter} that delegates to {@link TransactionAttributeSource#isCandidateClass}* for filtering classes whose methods are not worth searching to begin with.*/private class TransactionAttributeSourceClassFilter implements ClassFilter {@Overridepublic boolean matches(Class> clazz) {if (TransactionalProxy.class.isAssignableFrom(clazz) ||TransactionManager.class.isAssignableFrom(clazz) ||PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {return false;}TransactionAttributeSource tas = getTransactionAttributeSource();return (tas == null || tas.isCandidateClass(clazz));}}
重写了ClassFilter.matchs方法。对应AopUtils.canApply代码。
说明 TransactionAttributeSourceClassFilter#matchs 方法将被执行,最终走到AnnotationTransactionAttributeSource#isCandidateClass 方法。
if (!pc.getClassFilter().matches(targetClass)) {return false;}
private final Set annotationParsers;public AnnotationTransactionAttributeSource() {this(true);}public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {this.publicMethodsOnly = publicMethodsOnly;this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());}@Overridepublic boolean isCandidateClass(Class> targetClass) {for (TransactionAnnotationParser parser : this.annotationParsers) {if (parser.isCandidateClass(targetClass)) {return true;}}return false;}
发现isCandidateClass 调用SpringTransactionAnnotationParser.isCandidateClass 方法处理
@Overridepublic boolean isCandidateClass(Class> targetClass) {return AnnotationUtils.isCandidateClass(targetClass, Transactional.class);}
targetClass 是否标记Transactional注解.