定时器的实现原理 不消耗cpu_不一样的Spring事物实现原理

前言

在使用Spring声明式事物使用注解开发,十分的方便之前大概知道使用的是动态代理来实现的,今天来具体分析一下底层的实现细节。

环境准备

简单的搭建了一个SpirngBoot工程,加入了Spring Data Jpa作为数据访问层的框架。并在添加了一个简单的查询方法加上了事物注解。

@Servicepublic class UserServiceImpl implements UserService {    @Autowired    private UserRepository userRepository;    @Override    @Transactional(rollbackFor = Exception.class)    public List findAll() {        return userRepository.findAll();    }}复制代码

基础知识

2eebbbbdc0509bd4e0425df4a716fb91.png

@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;}复制代码

该注解import了TransactionManagementConfigurationSelector

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector {    /**     * 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);    }}复制代码

在org.springframework.transaction.annotation.TransactionManagementConfigurationSelector#selectImports方法中引入了两个重要的组件

  • AutoProxyRegistrar
  • ProxyTransactionManagementConfiguration

AutoProxyRegistrar

org.springframework.context.annotation.AutoProxyRegistrar#registerBeanDefinitions方法中调用了一个重要的方法AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)最终注册了InfrastructureAdvisorAutoProxyCreator。

a7efa0252105a31f0b429357e91b99ea.png

从继承图可以看出来InfrastructureAdvisorAutoProxyCreator是一个SmartInstantiationAwareBeanPostProcessor。需要重点关注AbstractAutoProxyCreator抽象类中的postProcessAfterInitialization

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {    @Override    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {        if (bean != null) {            Object cacheKey = getCacheKey(bean.getClass(), beanName);            if (this.earlyProxyReferences.remove(cacheKey) != bean) {                return wrapIfNecessary(bean, beanName, cacheKey);            }        }        return bean;    }            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;        }        // Create proxy if we have advice.        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;    }}复制代码

从上面的代码可以看出主要的功能是在bean实例化后创建了目标bean的代理对象,通过对目标对象的增强来达到对事物控制的目的。也就在controller层注入的userServiceImpl是Spring帮我们创建的代理对象。

ProxyTransactionManagementConfiguration

@Configurationpublic 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.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;    }}复制代码

该配置类配置了三个java bean

  • BeanFactoryTransactionAttributeSourceAdvisor
  • TransactionAttributeSource
  • TransactionInterceptor

在初始化ProxyTransactionManagementConfiguration的时候设置了TransactionAttributeSource事物解析器和TransactionInterceptor事物拦截器两个组件。上文提到的InfrastructureAdvisorAutoProxyCreator将两个组件串联了起来。

491da5b6e8d210e4ae45937fe1e5f09f.png


作者:cdtft
链接:https://juejin.im/post/6883776334590394376

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值