• 1.springboot开启代理


    1.概述

    springboot声明式事务是通过动态代理实现的,本文通过@EnableTransactionManagement做为入口,跟踪spring代理的开启过程;

    2.结论(重点)

    开启动态代理的功能就是引入动态代理创建器的bean定义(@EnableTransactionManagement引入InfrastructureAdvisorAutoProxyCreator)。动态代理创建器负责生成代理对象的动态代理,增强代理对象;

    3.原理

    实现方式

    spring声明式事务使用动态代理实现,实现有三种方式:

    • 如果类实现了接口,使用jdk提供的动态代理(默认);
    • 如果类没有实现接口,使用第三方库cglib,在运行时动态生成Java类的子类;
    • 使用AspectJ代理,在编译阶段生成AOP代理类,并将织入到Java字节码中。也称为静态代理;

    开启过程

    @EnableTransactionManagement

    使用@Import引入TransactionManagementConfigurationSelector;

    TransactionManagementConfigurationSelector

    默认的代理模式为PROXY,TransactionManagementConfigurationSelector的selectImports方法引入AutoProxyRegistrar和ProxyTransactionManagementConfiguration。AutoProxyRegistrar负责生成类的动态代理,其它通过动态代理实现有注解同样会引入AutoProxyRegistrar。比如@EnableCaching。ProxyTransactionManagementConfiguration为动态代理事务相关的配置;

    protected String[] selectImports(AdviceMode adviceMode) {
    	switch (adviceMode) {
    	 //**引入AutoProxyRegistrar和ProxyTransactionManagementConfiguration
    		case PROXY:
    			return new String[] {AutoProxyRegistrar.class.getName(),
    					ProxyTransactionManagementConfiguration.class.getName()};
    		case ASPECTJ:
    			return new String[] {determineTransactionAspectClass()};
    		default:
    			return null;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    AutoProxyRegistrar

    负责注册动态代理相关的bean定义(InfrastructureAdvisorAutoProxyCreator)。如果启用了CGLIB(proxyTargetClass=true)代理,在代理bean定义中添加属性proxyTargetClass=true;

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    	boolean candidateFound = false;
    	//**获取@EnableTransactionManagement注册所在类的所有注解(一般都是项目的启动类SpringdemoApplication)
    	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;
    			//**注册动态代理的bean定义(InfrastructureAdvisorAutoProxyCreator)
    			if (mode == AdviceMode.PROXY) {
    				AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
    				//**如果启用了CGLIB(proxyTargetClass=true),在代理bean定义中添加属性(definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);)
    				if ((Boolean) proxyTargetClass) {
    				    AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
    					return;
    				}
    			}
    		}
    	}
    	...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    AopConfigUtils.registerAutoProxyCreatorIfNecessary

    注册动态代理的bean定义InfrastructureAdvisorAutoProxyCreator。InfrastructureAdvisorAutoProxyCreator是基础设施自动代理创建器,只考虑基础设施(role=BeanDefinition.ROLE_INFRASTRUCTURE)的Advisor(Advisor:顾问,动态代理额外执行逻辑的抽象),不考虑自定义的Advisor;

    • BeanDefinition的role有三种类型:
      • ROLE_APPLICATION:表示这个Bean是用户自己定义的Bean,最常用的角色类型;
      • ROLE_SUPPORT:表示这个Bean是某些复杂配置的支撑部分。通常用于支持其他Bean的配置,例如一些中间件或者服务。
      • ROLE_INFRASTRUCTURE:表示这是一个Spring内部的Bean。通常用于实现Spring框架的核心功能,例如数据源、事务管理器等;
    • InfrastructureAdvisorAutoProxyCreator的作用
      • 创建代理对象,增强目标对象的功能。InfrastructureAdvisorAutoProxyCreator利用后置处理器机制,在对象创建以后,包装对象并返回代理对象。同时,通过拦截器链对代理对象执行的方法进行调用。
    @Nullable
    public static BeanDefinition registerAutoProxyCreatorIfNecessary(
    		BeanDefinitionRegistry registry, @Nullable Object source) {
        //**注册动态代理的bean定义InfrastructureAdvisorAutoProxyCreator
    	return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
    }
    
    //*获取动态代理的bean定义(名称为org.springframework.aop.config.internalAutoProxyCreator)
    //**如果当前的动态代理的bean定义不是InfrastructureAdvisorAutoProxyCreator,则根据优先级设置bean定义;
    //**InfrastructureAdvisorAutoProxyCreator优先级最低,并且没有提供修改优先级的方法;
    @Nullable
    private static BeanDefinition registerOrEscalateApcAsRequired(
    		Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
    	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;
    }
    
    //**动态代理bean的优先顺序,InfrastructureAdvisorAutoProxyCreator优先级最低
    static {
    	APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
    	APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
    	APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    4.默认配置

    实际上项目中通常是使用AnnotationAwareAspectJAutoProxyCreator创建cglib动态代理。因为spring有配置类AopAutoConfiguration,使用@EnableAspectJAutoProxy引入AnnotationAwareAspectJAutoProxyCreator,并默认proxyTargetClass=true;

    • 只要没有明确配置spring.aop.auto=false,就会使用AnnotationAwareAspectJAutoProxyCreator;
    • 只要没有明确配置spring.aop.proxy-target-class=false,就会使用cglib动态代理;
    @AutoConfiguration
    @ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
    public class AopAutoConfiguration {
    
    	@Configuration(proxyBeanMethods = false)
    	@ConditionalOnClass(Advice.class)
    	static class AspectJAutoProxyingConfiguration {
    
    		@Configuration(proxyBeanMethods = false)
    		@EnableAspectJAutoProxy(proxyTargetClass = false)
    		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")
    		static class JdkDynamicAutoProxyConfiguration {
    
    		}
    
    		@Configuration(proxyBeanMethods = false)
    		@EnableAspectJAutoProxy(proxyTargetClass = true)
    		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
    				matchIfMissing = true)
    		static class CglibAutoProxyConfiguration {
    
    		}
    
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    如果在声明式事务中想使用InfrastructureAdvisorAutoProxyCreator创建jdk动态代理,需加入以下配置;

    spring.aop.auto=false
    spring.aop.proxy-target-class=false
    
    • 1
    • 2
  • 相关阅读:
    java8新特性
    【交易误区】初学者常犯的MT4外汇交易错误有哪些?
    2022年0704-Com.Java.Basis 第十三课 《Java中的异常处理》经历前面的十二课的学习:我在思考在Java中报错如何处理
    No module named ‘pyqt5‘解决办法
    音视频从入门到精通——FFmpeg之av_read_frame函数分析
    GEE开发之Modis_LAI数据分析和获取
    linux12企业实战 -- 56 zabbix常规监控错误汇总
    python decorator
    SpringCloud (六) ——Gateway服务网关
    【RocketMQ】消息的刷盘机制
  • 原文地址:https://blog.csdn.net/zhouping118/article/details/133383162