springboot-EnableXX启用配置

启用配置

1.功能

  • 在springboot中使用@EnableXXX注解开启某项功能;
  • 常用的包括:
    • @EnableCaching:启用缓存
    • @EnableAsync:启用异步调用
    • @EnableScheduling:启用定时任务
    • @EnableTransactionManagement:启用事务

2.原理

2.1.说明

  • 使用@EnableXXX注解,相当于在spring上下文环境中导入一些java bean;
  • 可参考@EnableCaching和CachingConfigurationSelector,实现EnableXXX,导入一些需要初始化的java bean;

2.2.ImportSelector接口

  • 需要与@Import注解一起使用,导入selectImports返回类名的相关配置类;

2.3.过程

  • @EnableCaching注解配置上引入@Import注解;
  • @Import注解导入CachingConfigurationSelector实例;
  • @CachingConfigurationSelector继承AdviceModeImportSelector,并实现了ImportSelector接口;
  • AdviceModeImportSelector获取@EnableCaching注解配置的参数,传给CachingConfigurationSelector;
  • CachingConfigurationSelector根据@EnableCaching的配置及项目是否引入jsr107的接口定义和具体实现来决定需要导入哪些java bean;

3.解析

EnableCaching注解

  • 配置一些初始化参数,可传入到导入的CachingConfigurationSelector类中;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//**导入AsyncConfigurationSelector
@Import(CachingConfigurationSelector.class)
public @interface EnableCaching {
    //**是否启用CGLIB代理,默认不启用
	boolean proxyTargetClass() default false;
    //**代理方式:
    //**PROXY:Spring动态代理(含JDK动态代理和CGLIB)
	//**ASPECTJ:使用AspectJ静态代理
	AdviceMode mode() default AdviceMode.PROXY;
    //**注解的执行顺序
	int order() default Ordered.LOWEST_PRECEDENCE;
}

AdviceModeImportSelector抽象类

  • 读取EnableCaching注解中配置的参数,传给子类,并让子类决定需要导入bean的名称;
//**获取EnableCaching注解中的AdviceMode参数,并把AdviceMode传给子类,让子类决定需要导入bean的名称
public abstract class AdviceModeImportSelector<A extends Annotation> implements ImportSelector {

	@Override
	public final String[] selectImports(AnnotationMetadata importingClassMetadata) {
	    //**获取泛型的类型
		Class<?> annType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class);
		Assert.state(annType != null, "Unresolvable type argument for AdviceModeImportSelector");
		
        //**根据泛型的类型获取注解
		AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
		...
        
        //**获取注解中的AdviceMode参数
		AdviceMode adviceMode = attributes.getEnum(getAdviceModeAttributeName());
		//**把AdviceMode传给子类,让子类决定需要导入bean的名称
		String[] imports = selectImports(adviceMode);
		...
		return imports;
	}

	@Nullable
	protected abstract String[] selectImports(AdviceMode adviceMode);

}

CachingConfigurationSelector实现类

  • 根据EnableCaching注解中配置的参数,导入对应的java bean;
//**根据传入的AdviceMode参数,导入对应的bean
//**如果是PROXY代理模式,则导入AutoProxyRegistrar、ProxyCachingConfiguration。如果有jsr107的接口定义和具体实现,则额外导入ProxyJCacheConfiguration;
//**如果是ASPECTJ切面模式,则导入AspectJCachingConfiguration。如果有jsr107的接口定义和具体实现,则额外导入AspectJJCacheConfiguration;
//**以上导入的bean,大多是Configuration,各自会又会导入一些该功能依赖的bean;
public class CachingConfigurationSelector extends AdviceModeImportSelector<EnableCaching> {

	private static final String PROXY_JCACHE_CONFIGURATION_CLASS =
			"org.springframework.cache.jcache.config.ProxyJCacheConfiguration";

	private static final String CACHE_ASPECT_CONFIGURATION_CLASS_NAME =
			"org.springframework.cache.aspectj.AspectJCachingConfiguration";

	private static final String JCACHE_ASPECT_CONFIGURATION_CLASS_NAME =
			"org.springframework.cache.aspectj.AspectJJCacheConfiguration";


	private static final boolean jsr107Present;

	private static final boolean jcacheImplPresent;

	static {
		ClassLoader classLoader = CachingConfigurationSelector.class.getClassLoader();
		//**是否有jsr107的接口定义(jsr107是java缓存规范)
		jsr107Present = ClassUtils.isPresent("javax.cache.Cache", classLoader);
		//**是否有jsr107的具体实现
		jcacheImplPresent = ClassUtils.isPresent(PROXY_JCACHE_CONFIGURATION_CLASS, classLoader);
	}

    //**根据EnableCaching的mode参数决定导入的bean
	@Override
	public String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
			case PROXY:
				return getProxyImports();
			case ASPECTJ:
				return getAspectJImports();
			default:
				return null;
		}
	}

	//**PROXY代理模式
	private String[] getProxyImports() {
		List<String> result = new ArrayList<>(3);
		//**导入AutoProxyRegistrar
		result.add(AutoProxyRegistrar.class.getName());
		//**ProxyCachingConfiguration
		result.add(ProxyCachingConfiguration.class.getName());
		//**如果有jsr107的接口定义和具体实现,则导入ProxyJCacheConfiguration
		if (jsr107Present && jcacheImplPresent) {
			result.add(PROXY_JCACHE_CONFIGURATION_CLASS);
		}
		return StringUtils.toStringArray(result);
	}

	//**ASPECTJ切面模式
	private String[] getAspectJImports() {
		List<String> result = new ArrayList<>(2);
		//**导入AspectJCachingConfiguration
		result.add(CACHE_ASPECT_CONFIGURATION_CLASS_NAME);
		//**如果有jsr107的接口定义和具体实现,则导入AspectJJCacheConfiguration
		if (jsr107Present && jcacheImplPresent) {
			result.add(JCACHE_ASPECT_CONFIGURATION_CLASS_NAME);
		}
		return StringUtils.toStringArray(result);
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值