spring bean 作用域原理(Spring框架系列之bean的生命周期底层原理之数据库事务整合)
spring bean 作用域原理(Spring框架系列之bean的生命周期底层原理之数据库事务整合)另外咱们来回顾下,在Spring关于Bean的整个生命周期处理过程中,AOP处理发生的时间点以及处理的方式是怎样的呢?这个很重要,因为咱们不可能去修改Spring原有的代码,而只能利用Spring为咱们提供的扩展点来实现数据库的事务处理。而Spring针对事务的处理其实就是在不改动原有代码的情况下,如何添加上述第一步和第三步两个动作,要如何做到呢?其实我们考虑下整个需求,其实就是对原有的数据库操作做了增强的处理,而这个增强处理对于所有想要有事务处理的类来说都是相同的,而这其实就是Spring的AOP的典型应用场景,很明显这里咱们可以Spring的AOP。1.获取数据库连接,设置自动提交的值为false;2.执行SQL语句;3.如果SQL执行成功则执行提交,否则执行回滚操作。
Spring可以说是Java界使用最广泛的框架,没有之一,所以前面咱们花了16章的篇幅,把Spring框架的底层大概分析了一遍。到了这里,笔者觉得是时候开始讲下Spring对于数据库事务的处理机制了,其实只要老铁们把Spring的底层原理整明白了,完全可以自己去分析数据库事务的处理机制。
那么笔者就和大家一起来探讨下,如果是咱们自己来设计Spring对数据库的事务处理机制,咱们应该如何来思考!
要设计数据库的事务处理机制,那首先得了解在使用JDBC执行SQL的情况下,咱们是怎么处理事务的呢?
大概分为几个步骤:
1.获取数据库连接,设置自动提交的值为false;
2.执行SQL语句;
3.如果SQL执行成功则执行提交,否则执行回滚操作。
而Spring针对事务的处理其实就是在不改动原有代码的情况下,如何添加上述第一步和第三步两个动作,要如何做到呢?其实我们考虑下整个需求,其实就是对原有的数据库操作做了增强的处理,而这个增强处理对于所有想要有事务处理的类来说都是相同的,而这其实就是Spring的AOP的典型应用场景,很明显这里咱们可以Spring的AOP。
另外咱们来回顾下,在Spring关于Bean的整个生命周期处理过程中,AOP处理发生的时间点以及处理的方式是怎样的呢?这个很重要,因为咱们不可能去修改Spring原有的代码,而只能利用Spring为咱们提供的扩展点来实现数据库的事务处理。
正常情况下,Spring的AOP处理是发生在初始化后,而非正常情况下,也就是出现循环依赖的情况下,Spring会提前进行AOP,当然,不管是非正常情况或是正常情况,AOP的底层实现逻辑是一样的。
大家想起来这个底层逻辑了嘛?这里Spring会执行所有后置处理器的postProcessAfterInitialization方法,所以如果是咱们自己去实现,则是可以自己实现后置处理的逻辑,当然这里Spring给我们提供了专门用于AOP的抽象类:AbstractAutoProxyCreator,咱们继承这个类,实现指定的逻辑,当然这个指定的逻辑是啥,我们后面看Spring是怎么实现的。
我想这里的逻辑大概过程应该包括:将满足一定条件的类,生成代理对象,当操作这个代理对象的时候,所有的方法调用首先都会经过判断,该方法到底需不需要增强处理,如果需要,则会经过增强处理,也就是设置"自动提交值为false",当方法调用完成后,也会执行提交或回滚的增强逻辑,当然这些增强的逻辑有很多细节需要处理,比如如何跨事务处理等。
以上是我们的大概想法,那接下来,咱们看看Spring是如何处理数据库事务的,笔者将Spring的事务处理机制归结为几个大的步骤:注册后置处理器、生成代理对象、方法增强处理,下面详细描述每个步骤:
一、注册后置处理器
Spring通过增加注解EnableTransactionManagement来开启数据库事务,这个是数据库事务的入口,一切的起源就在这个注解类上:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement{......}
再看TransactionManagementConfigurationSelector:
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
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;
}
}
}
好,到这里,我们可以看到,Spring将会往Bean工厂中添加AutoProxyRegistrar和ProxyTransactionManagementConfiguration的Bean实例。
来继续看:
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
......
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;
if (mode == AdviceMode.PROXY) {
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
......
}
}
其中AnnotationConfigUtils.attributesFor(importingClassMetadata annType)这个方法,是获取EnableTransactionManagement注解的属性值,而AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)方法,则是注册一个InfrastructureAdvisorAutoProxyCreator类型的Bean,这个Bean的注册名称为:org.springframework.aop.config.internalAutoProxyCreator。
而ProxyTransactionManagementConfiguration则是一个配置类,其中定义了很多重要的Bean实例,其中一个实例类型:BeanFactoryTransactionAttributeSourceAdvisor,它是PointcutAdvisor的实现类,这个类表示啥意思呢?它是切点和代理逻辑(也就是Advice)的封装类,是生成AOP代理对象的核心参数,表示在调用代理对象时,需要对哪些方法进行增强,以及增强的代理逻辑:
@Configuration(proxyBeanMethods = false)
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.<Integer>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;
}
}
可以看出,切点是AnnotationTransactionAttributeSource对象,而TransactionInterceptor则是代理逻辑对象。
可以想想,这里所有代理对象的切点类都是AnnotationTransactionAttributeSource对象,代理逻辑都是TransactionInterceptor,代理逻辑是一个对象可以理解,因为都设置autocommit、提交事务、回滚事务都是相同的。而切点是同一个,则表明在这个AnnotationTransactionAttributeSource有很多的处理逻辑是针对某个具体的原始对象进行的,而事实上,也确实是这样。
二、生成代理对象
如上面所说,Spring向Bean工厂中添加了InfrastructureAdvisorAutoProxyCreator类型的对象,它的继承关系结构如下:
它是BeanPostProcessor的实现类,所以初始化完成后,会进入该类的postProcessAfterInitialization方法(这个方法是在AbstractAutoProxyCreator类中实现的),其中调用了方法wrapIfNecessary:
protected Object wrapIfNecessary(Object bean String beanName Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass() beanName)) {
this.advisedBeans.put(cacheKey Boolean.FALSE);
return bean;
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass() beanName null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey Boolean.TRUE);
Object proxy = createProxy(
bean.getClass() beanName specificInterceptors new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey Boolean.FALSE);
return bean;
}
其中getAdvicesAndAdvisorsForBean方法是关键,这里就是用来获取咱们上面说的BeanFactoryTransactionAttributeSourceAdvisor这个Advisor,我们直到,所有的Bean都会进入这个后置处理器的postProcessAfterInitialization方法,所以不可能是所有的Bean都会返回这个Advisor,一定是满足某些条件的Bean才会返回这个Advisor,那问题来了,这个条件是啥呢?
我们来一步步跟踪下就清楚了:
上述AbstractAutoProxyCreator会调用getAdvicesAndAdvisorsForBean获取Bean支持的所有Advisor,进入到findEligibleAdvisors方法中,在findEligibleAdvisors方法中,List<Advisor> candidateAdvisors = findCandidateAdvisors()会得到所有的Advisor,这里可以获取到我们上面定义的BeanFactoryTransactionAttributeSourceAdvisor,然后调用findAdvisorsThatCanApply方法进行过滤,判断满足条件的Advisor:
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass String beanName @Nullable TargetSource targetSource) {
//关键点入口
List<Advisor> advisors = findEligibleAdvisors(beanClass beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//关键点入口
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors beanClass beanName);
......
}
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors Class<?> beanClass String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
//关键点入口
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors beanClass);
}finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
public abstract class AopUtils{
......
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors Class<?> clazz) {
......
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
continue;
}
//关键点入口
if (canApply(candidate clazz hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
public static boolean canApply(Advisor advisor Class<?> targetClass boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
} else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
//关键点入口
return canApply(pca.getPointcut() targetClass hasIntroductions);
} else {
return true;
}
}
public static boolean canApply(Pointcut pc Class<?> targetClass boolean hasIntroductions) {
Assert.notNull(pc "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> 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;
}
哪些是满足条件的Advisor呢?这个逻辑是由AopUtils来进行处理,而最终的判断是methodMatcher.matches来进行判断,这个methodMatcher是个啥?它是BeanFactoryTransactionAttributeSourceAdvisor对象的TransactionAttributeSourcePointcut属性值,表示切点,它的matches方法:
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
public boolean matches(Method method Class<?> targetClass) {
TransactionAttributeSource tas = getTransactionAttributeSource();
//关键点入口
return (tas == null || tas.getTransactionAttribute(method targetClass) != null);
}
......
}
可以看到调用了TransactionAttributeSource类的TransactionAttributeSource方法,这里大家应该直到TransactionAttributeSource这个类对象是在哪里注入到Spring中的吧?对,它就是AnnotationTransactionAttributeSource对象。
从上面类的继承关系图上可以看到,最终会进入到AbstractFallbackTransactionAttributeSource的getTransactionAttribute方法
public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource {
public TransactionAttribute getTransactionAttribute(Method method @Nullable Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
Object cacheKey = getCacheKey(method targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return cached;
}
} else {
//关键点入口
TransactionAttribute txAttr = computeTransactionAttribute(method targetClass);
if (txAttr == null) {
this.attributeCache.put(cacheKey NULL_TRANSACTION_ATTRIBUTE);
}
else {
String methodIdentification = ClassUtils.getQualifiedMethodName(method targetClass);
if (txAttr instanceof DefaultTransactionAttribute) {
((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
}
if (logger.isTraceEnabled()) {
logger.trace("Adding transactional method '" methodIdentification "' with attribute: " txAttr);
}
this.attributeCache.put(cacheKey txAttr);
}
return txAttr;
}
}
}
而上述方法computeTransactionAttribute最终会调用SpringTransactionAnnotationParser的parseTransactionAnnotation来返回TransactionAttribute对象:
public class SpringTransactionAnnotationParser implements TransactionAnnotationParser Serializable {
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element Transactional.class false false);
if (attributes != null) {
return parseTransactionAnnotation(attributes);
} else {
return null;
}
}
}
上面如果被代理类类或方法上存在Transactional注解,则返回TransactionAttribute对象,否则返回null,这说明什么呢?说明只有被代理的类或方法上存在Transactional注解,才会返回BeanFactoryTransactionAttributeSourceAdvisor这个类型的Advisor对象,才会生成代理对象。
三、方法增强处理
这块涉及到具体的事务处理机制,咱们放到下一章节“Spring框架系列之bean的生命周期底层原理之事务处理机制?”详细分析。