欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring——@Enable***注解的工作原理

程序员文章站 2022-07-13 21:10:53
...

各种Enable

@EnableAspectJAutoProxy

@EnableAspectJAutoProxy注解 **Aspect自动代理
<aop:aspectj-autoproxy/>
开启对AspectJ自动代理的支持。

在用到AOP的自动代理的时候用,如果你理解了Java的动态代理,很容易的就会熟悉AOP的自动代理的。

@EnableAsync

@EnableAsync注解开启异步方法的支持。
这个相信大家都比较熟悉的。对于异步应该都理解的。

@EnableScheduling

@EnableScheduling注解开启计划任务的支持。
也就是字面上的意思,开启计划任务的支持!
一般都需要@Scheduled注解的配合。

@EnableWebMVC

@EnableWebMVC注解用来开启Web MVC的配置支持。
也就是写Spring MVC时的时候会用到。

@EnableConfigurationProperties

@EnableConfigurationProperties注解是用来开启对@ConfigurationProperties注解配置Bean的支持。
也就是@EnableConfigurationProperties注解告诉Spring Boot 使能支持@ConfigurationProperties

@EnableJpaRepositories

@EnableJpaRepositories注解开启对Spring Data JPA Repostory的支持。
Spring Data JPA 框架,主要针对的就是 Spring 唯一没有简化到的业务逻辑代码,至此,开发者连仅剩的实现持久层业务逻辑的工作都省了,唯一要做的,就只是声明持久层的接口,其他都交给 Spring Data JPA 来帮你完成!

@EnableTransactionManagement

@EnableTransactionManagement注解开启注解式事务的支持。
注解@EnableTransactionManagement通知Spring,@Transactional注解的类被事务的切面包围。这样@Transactional就可以使用了。

@EnableCaching

@EnableCaching注解开启注解式的缓存支持

通过这些简单的@Enable*可以开启一项功能的支持,从而避免自己配置大量的代码,很大程度上降低了使用难度。

观察下这些@Enable*注解的源码,可以发现所有的注解都有一个@Import注解。

@Import注解是用来导入配置类的,这也就是说这些自动开启的实现其实是导入了一些自动配置的Bean。

这些导入配置方式主要分为以下三种类型:

直接导入配置类
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({SchedulingConfiguration.class})
@Documented
public @interface EnableScheduling {
}

// 直接导入配置类SchedulingConfiguration
// 这个类注解了@Configuration,且注册了一个scheduledAnnotationProcessor的Bean
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class SchedulingConfiguration {

    @Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
        return new ScheduledAnnotationBeanPostProcessor();
    }
}

依据条件选择配置类

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {
    Class<? extends Annotation> annotation() default Annotation.class;
    boolean proxyTargetClass() default false;
    AdviceMode mode() default AdviceMode.PROXY;
    int order() default Ordered.LOWEST_PRECEDENCE;

}

// AsyncConfigurationSelector的根接口为ImportSelector
// 这个接口需要重写selectImports方法,在此方法内进行事先条件判断。

// 在下面的源码中,若adviceMode为PORXY,则返回ProxyAsyncConfiguration这个配置类。 
// 若activeMode为ASPECTJ,则返回AspectJAsyncConfiguration配置类。

public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {

    private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
            "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";

    /**
     * {@inheritDoc}
     * @return {@link ProxyAsyncConfiguration} or {@code AspectJAsyncConfiguration} for
     * {@code PROXY} and {@code ASPECTJ} values of {@link EnableAsync#mode()}, respectively
     */
    @Override
    public String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
            case PROXY:
                return new String[] { ProxyAsyncConfiguration.class.getName() };
            case ASPECTJ:
                return new String[] { ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME };
            default:
                return null;
        }
    }

}

动态注册Bean

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
    boolean proxyTargetClass() default false;
}
// ImportBeanDefinitionRegistrar的作用是在运行时自动添加Bean到已有的配置类
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * Register, escalate, and configure the AspectJ auto proxy creator based on the value
     * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
     * {@code @Configuration} class.
     */
    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        AnnotationAttributes enableAJAutoProxy =
                AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAJAutoProxy.getBoolean("proxyTargetClass")) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
    }
}

Ref:
https://blog.csdn.net/qq_26525215/article/details/53524844?utm_source=blogxgwz1