Spring Enable*高级应用及原理

Enable*

之前的文章用到了一些Enable*开头的注解,比如EnableAsync、EnableScheduling、EnableAspectJAutoProxy、EnableCaching等,Enable表示开启/允许一项功能。

Enable*工作原理

我们只需要几个很简单的注解就能开启一个复杂的功能,这是多么简易的用法,这是怎么办到的?

首先来看看计划任务@EnableScheduling的源代码

  1. @Target(ElementType.TYPE)

  2. @Retention(RetentionPolicy.RUNTIME)

  3. @Import(SchedulingConfiguration.class)

  4. @Documented

  5. public @interface EnableScheduling {

  6.  

  7. }

主要核心的配置就是导入了一个配置文件,所以谜底也就接开了。

@Import(SchedulingConfiguration.class)

@Import用法

来看看Import的源码

  1. @Target(ElementType.TYPE)

  2. @Retention(RetentionPolicy.RUNTIME)

  3. @Documented

  4. public @interface Import {

  5.  

  6.    /**

  7.     * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}

  8.     * or regular component classes to import.

  9.     */

  10.    Class<?>[] value();

  11.  

  12. }

1、Configuration

即上面的用法,直接导入Configuration配置类。

2、ImportSelector

根据条件选择导入不同的配置类,参考@EnableAsync

  1. @Target(ElementType.TYPE)

  2. @Retention(RetentionPolicy.RUNTIME)

  3. @Documented

  4. @Import(AsyncConfigurationSelector.class)

  5. public @interface EnableAsync {

  1. public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {

  2.  

  3.    private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =

  4.            "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";

  5.  

  6.    /**

  7.     * {@inheritDoc}

  8.     * @return {@link ProxyAsyncConfiguration} or {@code AspectJAsyncConfiguration} for

  9.     * {@code PROXY} and {@code ASPECTJ} values of {@link EnableAsync#mode()}, respectively

  10.     */

  11.    @Override

  12.    public String[] selectImports(AdviceMode adviceMode) {

  13.        switch (adviceMode) {

  14.            case PROXY:

  15.                return new String[] { ProxyAsyncConfiguration.class.getName() };

  16.            case ASPECTJ:

  17.                return new String[] { ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME };

  18.            default:

  19.                return null;

  20.        }

  21.    }

  22.  

  23. }

3、ImportBeanDefinitionRegistrar

动态注册Bean,参考@EnableAspectJAutoProxy

  1. @Target(ElementType.TYPE)

  2. @Retention(RetentionPolicy.RUNTIME)

  3. @Documented

  4. @Import(AspectJAutoProxyRegistrar.class)

  5. public @interface EnableAspectJAutoProxy {

  1. class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

  2.  

  3.    /**

  4.     * Register, escalate, and configure the AspectJ auto proxy creator based on the value

  5.     * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing

  6.     * {@code @Configuration} class.

  7.     */

  8.    @Override

  9.    public void registerBeanDefinitions(

  10.            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

  11.  

  12.        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

  13.  

  14.        AnnotationAttributes enableAspectJAutoProxy =

  15.                AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);

  16.        if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {

  17.            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);

  18.        }

  19.        if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {

  20.            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);

  21.        }

  22.    }

  23.  

  24. }

posted @ 2018-06-05 14:59  章鱼哥哥  阅读(202)  评论(0编辑  收藏  举报