第十三章 @Enable*註解的工作原理
阿新 • • 發佈:2019-01-11
在前面的章節中,我們使用了
@EnableAspectJAutoProxy開啟對AspectJ自動代理的支援
@EnableAsync開啟非同步方法的支援
@EnableScheduling開啟計劃任務的支援
通過簡單的@Enable*來開啟一項功能的支援,從而避免大量的配置,降低了使用難度,這是怎麼做到的呢?我們可以來研究一下這些註解的原碼
直接匯入配置類
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(SchedulingConfiguration.class)
@Documented
public @interface EnableScheduling {
}
直接匯入了配置類SchedulingConfiguration,再看SchedulingConfiguration的原始碼
@Configuration
public class SchedulingConfiguration {
@Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
return new ScheduledAnnotationBeanPostProcessor();
}
}
SchedulingConfiguration類註解了@Configuration,且註冊了一個ScheduledAnnotationBeanPostProcessor的Bean,而真正處理計劃任務的細節都是在這個Bean裡面。
依據條件選擇配置類
@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類,通過條件來選擇需要匯入的配置類。
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;
}
匯入AspectJAutoProxyRegistrar類,AspectJAutoProxyRegistrar實現了ImportBeanDefinitionRegistrar介面,ImportBeanDefinitionRegistrar的作用是在執行時自動新增Bean到已有的配置類。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@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);
}
}
}