1. 自定义的EnableXXX注解
- 自定义注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(XXXManagementConfigurationSelector.class)
public @interface EnableXXXManagement {
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default Ordered.LOWEST_PRECEDENCE;
}
- 配置Selector
EnableXXX
注解会在项目启动时,调用org.springframework.context.annotation.ImportSelector
接口的selectImports
方法。当然我们分析的是事务注解,最终使用的是AdviceModeImportSelector
注解。
public class XXXManagementConfigurationSelector extends AdviceModeImportSelector<EnableXXXManagement> {
@Override
protected String[] selectImports(AdviceMode adviceMode) {
//mode类型的不同
System.out.println("根据传入的mode,选择注册相应的Bean");
//注意Configuration的proxyBeanMethods 属性为false
return new String[]{
//实现了ImportBeanDefinitionRegistrar接口,即自动注册
MyAutoProxyRegistrar.class.getName(),
MyConfig.class.getName(),
MyAutoProxyRegistrar.class.getName()};
}
}
- 注册beanDefinition对象
将普通对象通过BeanDefinition
注册到Spring容器。无论是UService
还是XUserService
都是普通类,但是通过BeanDefinition
注册到Spring容器中。
registry.registerBeanDefinition("uuService", beanDefinition);
含义是将UService.class
注册为BeanDefinition
,且BeanName
为uuService
。注意,只注册的是BeanDefinition
对象,对象并没有去实例化。
依旧可以去修改BeanDefinition
的BeanClass类型
@Slf4j
public class MyAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//获取所有的注解
Set<String> annotationTypes = importingClassMetadata.getAnnotationTypes();
for (String anty : annotationTypes) {
AnnotationAttributes candidate = AnnotationAttributes.
fromMap(importingClassMetadata.getAnnotationAttributes(anty, false));
if (candidate == null) {
continue;
}
//获取注解属性
Object mode = candidate.get("mode"); //AdviceMode 枚举类型
Object proxyTargetClass = candidate.get("proxyTargetClass"); //Boolean类型
//判断是否是这个注解
if (mode != null && proxyTargetClass != null
&& AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) {
//注册Bean(获取BeanName)
if (registry.containsBeanDefinition("uuService")) {
BeanDefinition apcDefinition = registry.getBeanDefinition("uuService");
//修改BeanDefinition类型
apcDefinition.setBeanClassName(XUserService.class.getName());
log.info("Spring容器中存在bean对象");
continue;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(UService.class);
beanDefinition.setSource(null);
// beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//Bean的名字
registry.registerBeanDefinition("uuService", beanDefinition);
log.info("bean已经注册了");
}
}
}
}
- 测试
Configuration注解也是设置Spring容器,proxyBeanMethods=false
表明不会在项目启动时加载容器bean,而是需要手动开启(手动开启的方法如上所述)。
@Configuration(proxyBeanMethods = false)
public class MyConfig {
public MyConfig() {
System.out.println("实例化MyConfig容器;");
}
}
@Configuration
@EnableTransactionManagement //注册了一个自动代理器
@EnableXXXManagement(proxyTargetClass = true) //自定义注册器
public class DefaultAdvisorAutoProxyCreatorConfig {
@Bean("tService")
public TService tService() {
return new TService();
}
}
执行结果:项目启动时,会加载MyConfig
配置类。
public class TestProxyDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(DefaultAdvisorAutoProxyCreatorConfig.class);
//可以使用@Primary指定元素,或直接使用name名获取。
TService bean = (TService) applicationContext.getBean("tService");
Object us = applicationContext.getBean("uuService");
System.out.println(us);
}
}
根据传入的mode,选择注册相应的Bean
控制台-2020-01-04 16:24:56 [main] INFO com.example.demo.proxy.annotation.MyAutoProxyRegistrar - bean已经注册了
控制台-2020-01-04 16:24:56 [main] INFO com.example.demo.proxy.annotation.MyAutoProxyRegistrar - Spring容器中存在bean对象
控制台-2020-01-04 16:24:56 [main] INFO com.example.demo.proxy.annotation.MyAutoProxyRegistrar - Spring容器中存在bean对象
控制台-2020-01-04 16:24:56 [main] INFO com.example.demo.proxy.annotation.MyAutoProxyRegistrar - Spring容器中存在bean对象
实例化MyConfig容器;
控制台-2020-01-04 16:24:57 [main] INFO com.example.demo.proxy.XUserService - 初始化XUserService...
com.example.demo.proxy.XUserService@6253c26
2. Spring源码自动代理注册
@Configuration
@EnableTransactionManagement //注册了一个自动代理器
public class DefaultAdvisorAutoProxyCreatorConfig {
}
...
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
...
}
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
//一般我们使用代理的方式去使用事务,即PROXY
@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;
}
}
...
}
使用@EnableTransactionManagement
注解,完成AutoProxyRegistrar
和ProxyTransactionManagementConfiguration
的注册。
3. AutoProxyRegistrar 的注册
从字面意思上看:自动代理注册器,它是一个ImportBeanDefinitionRegistrar
的子类,可以实现自己向容器中注册Bean定义的信息。
当让这个接口是Spring交由子类去扩展的接口。那么registerBeanDefinitions
方法的两个参数是什么呢?
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
private final Log logger = LogFactory.getLog(getClass());
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
//根据注解类型获取AnnotationAttributes
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) {
//注册InfrastructureAdvisorAutoProxyCreator类型
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
//设置InfrastructureAdvisorAutoProxyCreator的属性proxyTargetClass=true(这样产生的代理对象为CGLIB代理)
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
if (!candidateFound && logger.isInfoEnabled()) {
//打印出info级别的日志
}
}
}
上述代码的含义,annTypes
是所有的注解类型,通过注解中的mode
和proxyTargetClass
属性可以找到特定的注解@EnableTransactionManagement
,然后注册自动代理器的BeanDefinition
对象。
注册自动生成器BeanDefinition:
public abstract class AopConfigUtils {
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
}
实际上注册的是InfrastructureAdvisorAutoProxyCreator
类型:
4. 自动代理的两种方式
开启事务注解,有两种方式,如上是@EnableTransactionManagement
注册的是InfrastructureAdvisorAutoProxyCreator
后置处理器。
实际上,也可以使用@EnableAspectJAutoProxy
注解来注册自动代理生成器。
@Configuration
@EnableTransactionManagement //事务注册器
@EnableAspectJAutoProxy //事务注册器
public class DefaultAdvisorAutoProxyCreatorConfig {
//目标类
@Bean("tService")
public TService tService() {
return new TService();
}
@Bean
public DataSource dataSource() throws PropertyVetoException {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUsername("root");
dataSource.setPassword("123456");
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
return jdbcTemplate;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
注册自动代理器的BeanDefinition:
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//注册自动代理器核心方法
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
public abstract class AopConfigUtils {
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);
static {
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//若已经注册了InfrastructureAdvisorAutoProxyCreator的BeanDefinition。
//且传入的Class类型在List的位置考上,那么替换BeanDefinition的BeanClass。
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) {
//替换BeanDefinition的BeanClass->AnnotationAwareAspectJAutoProxyCreator
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;
}
}
以上两个@EnableXX
注解的执行是代码中出现的顺序,由上而下执行,无论顺序如何,最终会生成一个org.springframework.aop.config.internalAutoProxyCreator
名字的AnnotationAwareAspectJAutoProxyCreator
对象。
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(DefaultAdvisorAutoProxyCreatorConfig.class);
//可以使用@Primary指定元素,或直接使用name名获取。
TService bean = (TService) applicationContext.getBean("tService");
applicationContext.getBean(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
System.out.println(bean1.getClass());
}
输出结果:
class org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator