Spring Enable*高级应用及原理
Enable*
之前的文章用到了一些Enable*开头的注解,比如EnableAsync、EnableScheduling、EnableAspectJAutoProxy、EnableCaching等,Enable表示开启/允许一项功能。
Enable*工作原理
我们只需要几个很简单的注解就能开启一个复杂的功能,这是多么简易的用法,这是怎么办到的?
首先来看看计划任务@EnableScheduling的源代码
-
@Target(ElementType.TYPE)
-
@Retention(RetentionPolicy.RUNTIME)
-
@Import(SchedulingConfiguration.class)
-
@Documented
-
public @interface EnableScheduling {
-
-
}
主要核心的配置就是导入了一个配置文件,所以谜底也就接开了。
@Import(SchedulingConfiguration.class)
@Import用法
来看看Import的源码
-
@Target(ElementType.TYPE)
-
@Retention(RetentionPolicy.RUNTIME)
-
@Documented
-
public @interface Import {
-
-
/**
-
* {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
-
* or regular component classes to import.
-
*/
-
Class<?>[] value();
-
-
}
1、Configuration
即上面的用法,直接导入Configuration配置类。
2、ImportSelector
根据条件选择导入不同的配置类,参考@EnableAsync
-
@Target(ElementType.TYPE)
-
@Retention(RetentionPolicy.RUNTIME)
-
@Documented
-
@Import(AsyncConfigurationSelector.class)
-
public @interface EnableAsync {
-
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、ImportBeanDefinitionRegistrar
动态注册Bean,参考@EnableAspectJAutoProxy
-
@Target(ElementType.TYPE)
-
@Retention(RetentionPolicy.RUNTIME)
-
@Documented
-
@Import(AspectJAutoProxyRegistrar.class)
-
public @interface EnableAspectJAutoProxy {
-
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 enableAspectJAutoProxy =
-
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
-
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
-
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
-
}
-
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
-
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
-
}
-
}
-
-
}