CacheAutoConfiguration自动配置类

2,377 阅读2分钟

SpringBoot从文件路径下的META-ING/spring.factories中读入需要配置的类的名称。然后用资源加载器加载注册到IoC容器中,尽心解析注解为Bean Definiton。但是不是所有的都能初始化为Bean,只有满足条件的类才能初始化我Bean。是由一些条件注解来判断的

例如下面的CacehAutoConfiguration

// 这是一个配置类,可以被ConfigurationClassParser解析器进行注解解析
@Configuration(proxyBeanMethods = false)
// 条件注解必须存在CacheManager类
@ConditionalOnClass(CacheManager.class)
// 必须有一个CacheAspectSupport Bean存在在IoC容器中
// 该Bean是由@EnabelCache来加载的,所以要使用Spring Cache就必须对 主引导类标注@EnableCache
@ConditionalOnBean(CacheAspectSupport.class)
// 不存在CacheManeger Bean
@ConditionalOnMissingBean(value = CacheManager.class, name = "cacheResolver")
@EnableConfigurationProperties(CacheProperties.class)
@AutoConfigureAfter({ CouchbaseAutoConfiguration.class, HazelcastAutoConfiguration.class,
		HibernateJpaAutoConfiguration.class, RedisAutoConfiguration.class })
		
// 导入CacheManager 这是在满足所有条件对CacheAutoConfiguration进行加载注解的时候才能触发的操作
@Import({ CacheConfigurationImportSelector.class, CacheManagerEntityManagerFactoryDependsOnPostProcessor.class })
public class CacheAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean
	public CacheManagerCustomizers cacheManagerCustomizers(ObjectProvider<CacheManagerCustomizer<?>> customizers) {
		return new CacheManagerCustomizers(customizers.orderedStream().collect(Collectors.toList()));
	}

	@Bean
	public CacheManagerValidator cacheAutoConfigurationValidator(CacheProperties cacheProperties,
			ObjectProvider<CacheManager> cacheManager) {
		return new CacheManagerValidator(cacheProperties, cacheManager);
	}

	@ConditionalOnClass(LocalContainerEntityManagerFactoryBean.class)
	@ConditionalOnBean(AbstractEntityManagerFactoryBean.class)
	static class CacheManagerEntityManagerFactoryDependsOnPostProcessor
			extends EntityManagerFactoryDependsOnPostProcessor {

		CacheManagerEntityManagerFactoryDependsOnPostProcessor() {
			super("cacheManager");
		}

	}

	/**
	 * Bean used to validate that a CacheManager exists and provide a more meaningful
	 * exception.
	 */
	static class CacheManagerValidator implements InitializingBean {

		private final CacheProperties cacheProperties;

		private final ObjectProvider<CacheManager> cacheManager;

		CacheManagerValidator(CacheProperties cacheProperties, ObjectProvider<CacheManager> cacheManager) {
			this.cacheProperties = cacheProperties;
			this.cacheManager = cacheManager;
		}

		@Override
		public void afterPropertiesSet() {
			Assert.notNull(this.cacheManager.getIfAvailable(),
					() -> "No cache manager could be auto-configured, check your configuration (caching " + "type is '"
							+ this.cacheProperties.getType() + "')");
		}

	}

	/**
	 * {@link ImportSelector} to add {@link CacheType} configuration classes.
	 */
	static class CacheConfigurationImportSelector implements ImportSelector {

		@Override
		public String[] selectImports(AnnotationMetadata importingClassMetadata) {
			CacheType[] types = CacheType.values();
			String[] imports = new String[types.length];
			for (int i = 0; i < types.length; i++) {
			// 读取org.springframework.boot.autoconfigure.cache.***CacheConfiguration
			// 
				imports[i] = CacheConfigurations.getConfigurationClass(types[i]);
			}
			return imports;
		}

	}

}

CacheConfigurationImportSelector会读入下面这些配置类,但是并不是每个配置类都满足条件,所以一般没有引入其他缓存中间件入Redis时,会使用SimpleCacheConfiguration来注册CacheManager。但是在有缓存中间件存在的情况下,由于SimpleCacheConfiguration是在最后面,所以优先使用其他,此时就不会用SimpleCacheConfiguration。这也是为什么在有Redis存在的情况下,会自动使用RedisCacheManager,将Redis作为缓存。

@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(CacheManager.class)
@Conditional(CacheCondition.class)
class SimpleCacheConfiguration {

	@Bean
	ConcurrentMapCacheManager cacheManager(CacheProperties cacheProperties,
			CacheManagerCustomizers cacheManagerCustomizers) {
		ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
		List<String> cacheNames = cacheProperties.getCacheNames();
		if (!cacheNames.isEmpty()) {
			cacheManager.setCacheNames(cacheNames);
		}
		return cacheManagerCustomizers.customize(cacheManager);
	}

}