Дополнительные темы Spring 4.x (6): как работают аннотации @Enable*

задняя часть WeChat Spring API

Пройдено в предыдущей серии статей:
1. @EnableAspectJAutoProxyоткрытая параAspectJавтоматическая поддержка прокси,оригинальный клик:Базовая конфигурация Spring4.x (3): Spring AOP.
2. @EnableAsyncВключить поддержку асинхронных методов,оригинальный клик:Дополнительные темы Spring 4.x (2): многопоточность.
3. @EnableSchedulingВключите поддержку запланированных задач,оригинальный клик:Расширенные темы Spring 4.x (3): запланированные задачи.
В следующей серии статей SpringMvc будет задействовано использование другого @Enable* через:
1. @EnableWebMvcвключиWeb MVCподдержка конфигурации.
2. @EnableConfigurationPropertiesоткрытая пара@ConfigurationPropertiesКонфигурация аннотацииBeanслужба поддержки.
3. @EnableJpaRepositories открытая параSpring Data JPA Repositoryслужба поддержки.
4. @EnableTransactionManagementВключает поддержку аннотированных транзакций.
5. @EnableCachingВключить поддержку кэша аннотаций.

через простой@Enable*Чтобы открыть поддержку функции, чтобы избежать самостоятельной настройки большого количества кода, что значительно снижает сложность использования. Так каков же принцип реализации этой магической функции? Давайте изучим это.

@Configuration
public class SchedulingConfiguration {

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

}

наблюдая за этими@Enable*В исходном коде аннотации обнаружено, что все аннотации имеют@Importаннотация,@ImportОн используется для импорта классов конфигурации, что означает, что эти автоматически включенные реализации фактически импортируют некоторые автоматически настроенные компоненты. Эти импортированные конфигурации в основном делятся на следующие три типа:

1. Первая категория: напрямую импортировать класс конфигурации

@Target({java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({SchedulingConfiguration.class})
@Documented
public @interface EnableScheduling
{
}

можно увидетьEnableSchedulingПРИМЕЧАНИЕ Прямой класс конфигурации импортаSchedulingConfiguration, этот класс аннотируется@Configurationи зарегистрировалscheduledAnnotationProcessorБин,SchedulingConfigurationИсходный код выглядит следующим образом:

@Configuration
public class SchedulingConfiguration {

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

}

2. Вторая категория: выберите категорию конфигурации в соответствии с условиями

@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;
}

AsyncConfigurationSelectortВыберите класс конфигурации, который необходимо импортировать по условию.AsyncConfigurationSelectorКорневой интерфейсImportSelector, этот интерфейс нужно переписатьselectImportsметод, при котором выносится предварительное суждение. В этом примере, еслиadviceModeдляPROXY, затем вернутьсяProxyAsyncConfigurationЭтот класс конфигурации; еслиadviceModeдля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;
        }
    }

}

3. Третья категория: динамическая регистрация бинов

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

    /**
     * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
     * to standard Java interface-based proxies. The default is {@code false}.
     */
    boolean proxyTargetClass() default false;

}

AspectJAutoProxyRegistrarДостигнутоImportBeanDefinitionRegistrarинтерфейс,ImportBeanDefinitionRegistrarФункция состоит в том, чтобы автоматически добавлять bean-компоненты в существующие классы конфигурации во время выполнения, переопределяя метод:

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)

в,AnnotationMetadataПараметр используется для получения аннотации к текущему классу конфигурации,BeanDefinitionRegistry Параметры используются для регистрации бинов. Исходный код выглядит следующим образом:

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);
        }
    }

}
награда Добро пожаловать в публичный аккаунт Life Designer в WeChat.
Публичный идентификатор: longjiazuoA