0
点赞
收藏
分享

微信扫一扫

SpringAOP联盟(9)-自动代理器的注册

杰森wang 2021-09-28 阅读 24

1. 自定义的EnableXXX注解

  1. 自定义注解:
@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;
}
  1. 配置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()};
    }
}
  1. 注册beanDefinition对象

将普通对象通过BeanDefinition注册到Spring容器。无论是UService还是XUserService都是普通类,但是通过BeanDefinition注册到Spring容器中。

registry.registerBeanDefinition("uuService", beanDefinition);含义是将UService.class注册为BeanDefinition,且BeanNameuuService。注意,只注册的是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已经注册了");
            }
        }
    }
}
  1. 测试
    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注解,完成AutoProxyRegistrarProxyTransactionManagementConfiguration的注册。

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是所有的注解类型,通过注解中的modeproxyTargetClass属性可以找到特定的注解@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

举报

相关推荐

0 条评论