zoukankan      html  css  js  c++  java
  • Spring中的@Enable注解

    本文转载自SpringBoot中神奇的@Enable注解?

    导语

    在SpringBoot开发过程,我们经常会遇到@Enable开始的好多注解,比如@EnableEurekaServer、@EnableAsync、@EnableScheduling等,今天我们就来分析下这些注解到底是如何工作的?

    @Enable实现的原理

    通过这些@Enable注解的源码可以看出,所有@Enable注解里面都有一个@Import注解,而@Import是用来导入配置类的,所以@Enable自动开启的实现原理其实就是导入了一些自动配置的Bean。

    @Import注解的用法

    @Import只允许放到类上面,不能放到方法上。
    @Import注解允许导入@Configuration类,ImportSelector和ImportBeanDefinitionRegistrar的实现类,普通的Bean。

    有以下三种使用方式

    直接导入配置类

    @EnableEurekaServer使用了这种方式,注解源码如下:

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import({EurekaServerMarkerConfiguration.class})
    public @interface EnableEurekaServer {
    }
    

    可以看到@EnableEurekaServer注解直接导入了配置类EurekaServerMarkerConfiguration,而这个配置类中向spring容器中注册了一个EurekaServerMarkerConfiguration的Bean。

    EurekaServerMarkerConfiguration的源码如下:

    @Configuration
    public class EurekaServerMarkerConfiguration {
        public EurekaServerMarkerConfiguration() {
        }
    
        @Bean
        public EurekaServerMarkerConfiguration.Marker eurekaServerMarkerBean() {
            return new EurekaServerMarkerConfiguration.Marker();
        }
    
        class Marker {
            Marker() {
            }
        }
    }
    

    依据条件选择配置类

    @EnableAsync使用了这种方式,注解源码如下:

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

    EnableAsync注解中导入了AsyncConfigurationSelector,AsyncConfigurationSelector通过条件来选择需要导入的配置类,继承AdviceModeImportSelector又实现了ImportSelector接口,接口重写selectImports方法进行事先条件判断PROXY或者ASPECTJ选择不同的配置类。

    AsyncConfigurationSelector源码如下:

    public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
    
    	private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
    			"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
    
    
    	/**
    	 * Returns {@link ProxyAsyncConfiguration} or {@code AspectJAsyncConfiguration}
    	 * for {@code PROXY} and {@code ASPECTJ} values of {@link EnableAsync#mode()},
    	 * respectively.
    	 */
    	@Override
    	@Nullable
    	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

    @EnableAspectJAutoProxy使用了这种方式,注解源码如下:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(AspectJAutoProxyRegistrar.class)
    public @interface EnableAspectJAutoProxy {
    
    	boolean proxyTargetClass() default false;
    	 
    	boolean exposeProxy() default false;
    }
    

    EnableAspectJAutoProxy注解中导入了AspectJAutoProxyRegistrar,AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,在运行时把Bean注册到spring容器中。

    AspectJAutoProxyRegistrar的源码如下:

    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 != null) {
    			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
    				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
    			}
    			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
    				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
    			}
    		}
    	}
    
    }
    
  • 相关阅读:
    WPF Step By Step -基础知识介绍
    WPF Step By Step 系列
    设计模式的六大原则
    Java实现二维码生成的方法
    Java 导出Excel
    解析图书 XML
    Maven搭建Spring+SpringMVC+Mybatis+Shiro项目详解
    springboot配置文件的所有属性
    SpringBoot中 application.yml /application.properties常用配置介绍
    Linux 系统目录结构
  • 原文地址:https://www.cnblogs.com/yungyu16/p/13226880.html
Copyright © 2011-2022 走看看