概述
spring.factories——实现类设计思想
面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则
如果
需要替换一种实现,就需要修改代码
。为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制
spring.factories就是一套SPI的服务发现编程方式,让很多接口组合在这里统一表现以及明确实现类分布在何处,而不需要在代码里一个个去找
spring.factories——文件扫描
SpringBoot在启动的时候,会扫描在每个maven包下面的/META-INF/spring.factories这个文件,在这个文件中找到所有必要的类并实例化他们用于完成SpringBoot自动配置的功能;
SpringBootApplication 注解包含了@EnableAutoConfiguration
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}
@EnableAutoConfiguration注册了AutoConfigurationImportSelector作为选择器
所以ioc在初始化的时候就会用这个自动配置类选择器运行自动配置相关代码,这些都ioc直接完成的,所以我接下来直接看AutoConfigurationImportSelector
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}
AutoConfigurationImportSelector 中的AutoConfigurationGroup
返回一个class类型,ioc会直接创建这个类型的实例
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
public Class<? extends Group> getImportGroup() {
return AutoConfigurationGroup.class;
}
}
题外:ConfigurationClassParser调用process
ConfigurationClassParser专用于ioc中解析配置类,该类会解析@Import标签实例化里面的类,并调用group的process方法
class ConfigurationClassParser {
private static class DeferredImportSelectorGrouping {
public Iterable<Group.Entry> getImports() {
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
return this.group.selectImports();
}
}
}
AutoConfigurationGroup的process实现
private static class AutoConfigurationGroup
implements DeferredImportSelector.Group, BeanClassLoaderAware, BeanFactoryAware, ResourceLoaderAware {
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
/*
获取自动配置数组
*/
AutoConfigurationEntry autoConfigurationEntry =
((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(annotationMetadata);
}
}
AutoConfigurationImportSelector获取配置信息
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
/*
找到所有类的string描述
*/
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
/*
回调事件
*/
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
/*
回调onAutoConfigurationImportEvent事件
*/
private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();
if (!listeners.isEmpty()) {
AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
for (AutoConfigurationImportListener listener : listeners) {
invokeAwareMethods(listener);
listener.onAutoConfigurationImportEvent(event);
}
}
}
/*
调用SpringFactoriesLoader开始读取
*/
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
return configurations;
}
}
SpringFactoriesLoader 读取配置文件
public final class SpringFactoriesLoader {
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
/*
FACTORIES_RESOURCE_LOCATION就是META-INF/spring.factories
*/
try {
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
}
}
spring.factories——举例应用
以RedisAutoConfiguration为例,看看他是如何实现自动配置的;
RedisAutoConfiguration在META-INF/spring.factories中服务发现后,会被实例化成为ioc容器内的bean,此时我们只需要看待普通bean去看待这个RedisAutoConfiguration 即可;
我们发现
(1)@EnableConfigurationProperties引入了RedisProperties的配置数据信息
(2)@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })引入了redis的两个配置类信息
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
@EnableConfigurationProperties
直接用选择器引入了@EnableConfigurationPropertiesRegistrar**
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EnableConfigurationPropertiesRegistrar.class)
public @interface EnableConfigurationProperties {
}
class EnableConfigurationPropertiesRegistrar implements ImportBeanDefinitionRegistrar {
/*
利用注解注册这些properties,比如上面的RedisProperties对象就是来在于springboot的集中化配置
*/
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
registerInfrastructureBeans(registry);
ConfigurationPropertiesBeanRegistrar beanRegistrar = new ConfigurationPropertiesBeanRegistrar(registry);
getTypes(metadata).forEach(beanRegistrar::register);
}
}
LettuceConnectionConfiguration
利用构造器注入了ioc的RedisProperties,传给父类RedisConnectionConfiguration 去保存着
class LettuceConnectionConfiguration extends RedisConnectionConfiguration {
LettuceConnectionConfiguration(RedisProperties properties,
ObjectProvider<RedisSentinelConfiguration> sentinelConfigurationProvider,
ObjectProvider<RedisClusterConfiguration> clusterConfigurationProvider) {
super(properties, sentinelConfigurationProvider, clusterConfigurationProvider);
}
}
spring.factories——文件内容
spring.factories就是一套SPI的服务发现编程方式,让很多接口组合在这里统一表现以及明确实现类分布在何处,而不需要在代码里一个个去找
EnableAutoConfiguration
完成自动配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration
AutoConfigurationImportFilter
完成过滤注入注解的实现
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=
org.springframework.boot.autoconfigure.condition.OnBeanCondition,
org.springframework.boot.autoconfigure.condition.OnClassCondition,
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
其他
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
org.springframework.context.ApplicationListener=
org.springframework.boot.autoconfigure.BackgroundPreinitializer
org.springframework.context.ApplicationContextInitializer=
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListene
org.springframework.boot.diagnostics.FailureAnalyzer=
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,
org.springframework.boot.autoconfigure.flyway.FlywayMigrationScriptMissingFailureAnalyzer,
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,
org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryBeanCreationFailureAnalyzer,
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider
最后
以上就是甜蜜耳机为你收集整理的【框架专题】——管理型容器——SpringBoot自动配置原理与SPI编程风格的全部内容,希望文章能够帮你解决【框架专题】——管理型容器——SpringBoot自动配置原理与SPI编程风格所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复