前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >@Enable***注解的原理与使用

@Enable***注解的原理与使用

作者头像
IT云清
发布2019-01-22 10:34:38
7180
发布2019-01-22 10:34:38
举报
文章被收录于专栏:IT云清IT云清

摘要:我们在开发中,会经常用到@Enable***开头的这种注解,来自动导入一些框架配置的默认的bean,进入注解源码,会发现这些注解类上都会有一个@Import(****.class)注解,这些注解是怎么实现的呢?

Import导入,又分为三种方式,分别为:

1.直接导入配置类

2.根据条件选择配置类

3.动态注册Bean

下面,通过示例,进入源码,分析一下这三种导入方式:

1.直接导入配置类

以@EnableScheduling为例,看源码:

代码语言:javascript
复制
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(SchedulingConfiguration.class)
@Documented
public @interface EnableScheduling {

}

发现有@Import导入了一个SchedulingConfiguration类,我们追一下源码:

代码语言:javascript
复制
package org.springframework.scheduling.annotation;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.scheduling.config.TaskManagementConfigUtils;

/**
 * {@code @Configuration} class that registers a {@link ScheduledAnnotationBeanPostProcessor}
 * bean capable of processing Spring's @{@link Scheduled} annotation.
 *
 * <p>This configuration class is automatically imported when using the
 * {@link EnableScheduling @EnableScheduling} annotation. See
 * {@code @EnableScheduling}'s javadoc for complete usage details.
 *
 * @author Chris Beams
 * @since 3.1
 * @see EnableScheduling
 * @see ScheduledAnnotationBeanPostProcessor
 */
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class SchedulingConfiguration {

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

}

解读一下注释,看看此类的作用:

为@Scheduled注解注册一个能被spring管理的名为:ScheduledAnnotationBeanPostProcessor的bean,当使用@EnableScheduling注解时,这个注解类会自动被导入

2.根据条件选择配置类

以@EnableAsync注解为例,看源码:

代码语言:javascript
复制
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {省略....}

发现有@Import导入了一个AsyncConfigurationSelector类,我们追一下源码:

代码语言:javascript
复制
package org.springframework.scheduling.annotation;

import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.AdviceModeImportSelector;

/**
 * Selects which implementation of {@link AbstractAsyncConfiguration} should be used based
 * on the value of {@link EnableAsync#mode} on the importing {@code @Configuration} class.
 *
 * @author Chris Beams
 * @since 3.1
 * @see EnableAsync
 * @see ProxyAsyncConfiguration
 */
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;
		}
	}

}

这个类的父父类是ImportSelector,其实是一个选择器,这个ImportSelector接口中只有一个方法

代码语言:javascript
复制
String[] selectImports(AnnotationMetadata importingClassMetadata);

AsyncConfigurationSelector类中重写了这个选择方法,根据不同的参数(adviceMode,我理解为框架建议的类型),会返回不同的配置类:

若adviceMode为PORXY,则返回ProxyAsyncConfiguration这个配置类。 若activeMode为ASPECTJ,则返回AspectJAsyncConfiguration配置类。

3.动态注册Bean

以@EnableAspectJAutoProxy为例,查看源码:

代码语言:javascript
复制
@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;

	/**
	 * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
	 * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
	 * Off by default, i.e. no guarantees that {@code AopContext} access will work.
	 * @since 4.3.1
	 */
	boolean exposeProxy() default false;

}

此类导入了AspectJAutoProxyRegistrar类,这个类实现了父类的registerBeanDefinitions()方法,此方法根据给定的注解定义来动态注册bean。

4.@Configuration源码分析

代码语言:javascript
复制
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {

	/**
	 * Explicitly specify the name of the Spring bean definition associated
	 * with this Configuration class. If left unspecified (the common case),
	 * a bean name will be automatically generated.
	 * <p>The custom name applies only if the Configuration class is picked up via
	 * component scanning or supplied directly to a {@link AnnotationConfigApplicationContext}.
	 * If the Configuration class is registered as a traditional XML bean definition,
	 * the name/id of the bean element will take precedence.
	 * @return the suggested component name, if any (or empty String otherwise)
	 * @see org.springframework.beans.factory.support.DefaultBeanNameGenerator
	 */
	String value() default "";

}

@Configuration注解的源码中其实是没什么内容的。我们看一下这段注解的意思:

显示的指定配置文件中定义的spring bean的名字,一般情况下,如果未显示的指明,将会自动生成一个bean的名字;

自定义名称,仅在配置类通过组件扫描或者由程序上下文直接给出时,才可以使用;

如果配置类是以xml的形式定义的,那xml中定义的bean名字将优先起作用;

此接口将会返回框架建议的组件名称,如果有的话,否则返回空字符串。

5.常用注解

@EnableAspectJAutoProxy @EnableAspectJAutoProxy注解 激活Aspect自动代理,开启对AspectJ自动代理的支持。 @EnableAsync @EnableAsync注解开启异步方法的支持。 @EnableScheduling @EnableScheduling注解开启计划任务的支持。 @EnableWebMVC @EnableWebMVC注解用来开启Web MVC的配置支持,也就是写Spring MVC时的时候会用到。 @EnableConfigurationProperties @EnableConfigurationProperties注解是用来开启对@ConfigurationProperties注解配置Bean的支持。 @EnableJpaRepositories @EnableJpaRepositories注解开启对Spring Data JPA Repostory的支持。 @EnableTransactionManagement @EnableTransactionManagement注解开启注解式事务的支持,注解@EnableTransactionManagement通知Spring,@Transactional注解的类被事务的切面包围。这样@Transactional就可以使用了。 @EnableCaching @EnableCaching注解开启注解式的缓存支持

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年02月05日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档