springboot spring.factories说明
********************
spring.factories 简介
springboot-autoconfigure META-INF/spring.factories(部分)
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.autoconfigure.integration.IntegrationPropertiesEnvironmentPostProcessor
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
。。。
key = value:value可为多个,多个值之间用逗号间隔
常见应用
自定义springboot starter
将类写在org.springframework.boot.autoconfigure.EnableAutoConfiguration=\下,
实现类的注入(包括项目中的类、项目路径外的类)
********************
springboot 自动装配原理
加载spring.factories自动配置类调用栈
# SpringFactoriesLoader loadFactoryNames方法加载自动配置类
org.springframework.core.io.support.SpringFactoriesLoader.loadFactoryNames(SpringFactoriesLoader.java:132)
# AutoConfigurationImportSelector
org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getCandidateConfigurations(AutoConfigurationImportSelector.java:178)
org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getAutoConfigurationEntry(AutoConfigurationImportSelector.java:123)
org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup.process(AutoConfigurationImportSelector.java:434)
# ConfigurationClassParser
org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGrouping.getImports(ConfigurationClassParser.java:879)
org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:809)
org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:780)
org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:193)
# ConfigurationClassPostProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:331)
org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247)
# PostProcessorRegistrationDelegate
org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311)
org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112)
# AbstractApplicationContext
org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746)
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564)
# ServletWebServerApplicationContext refresh方法
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
# SpringApplication refresh方法
org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434)
# SpringApplication run方法
org.springframework.boot.SpringApplication.run(SpringApplication.java:338)
org.springframework.boot.SpringApplication.run(SpringApplication.java:1343)
org.springframework.boot.SpringApplication.run(SpringApplication.java:1332)
# springboot 项目启动
com.example.demo.DemoApplication.main(DemoApplication.java:10)
说明:springboot 版本不同,调用路径可能不一致
SpringFactoriesLoader
public final class SpringFactoriesLoader {
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);
static final Map<ClassLoader, Map<String, List<String>>> cache = new ConcurrentReferenceHashMap();
private SpringFactoriesLoader() {
}
public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
//获取key=factoryType.getName(),对应所有value的实例对象
Assert.notNull(factoryType, "'factoryType' must not be null");
ClassLoader classLoaderToUse = classLoader;
if (classLoader == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
List<String> factoryImplementationNames = loadFactoryNames(factoryType, classLoaderToUse);
if (logger.isTraceEnabled()) {
logger.trace("Loaded [" + factoryType.getName() + "] names: " + factoryImplementationNames);
}
List<T> result = new ArrayList(factoryImplementationNames.size());
Iterator var5 = factoryImplementationNames.iterator();
while(var5.hasNext()) {
String factoryImplementationName = (String)var5.next();
result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse));
}
AnnotationAwareOrderComparator.sort(result);
return result;
}
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
//获取key=factoryType.getName(),对应的所有value的全限定名
ClassLoader classLoaderToUse = classLoader;
if (classLoader == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
//key:spring.factories中键值对的key
//List<String>:key对应的value集合
Map<String, List<String>> result = (Map)cache.get(classLoader);
if (result != null) {
return result;
} else {
HashMap result = new HashMap();
try {
Enumeration urls = classLoader.getResources("META-INF/spring.factories");
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
Iterator var6 = properties.entrySet().iterator();
while(var6.hasNext()) {
Entry<?, ?> entry = (Entry)var6.next();
String factoryTypeName = ((String)entry.getKey()).trim();
String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
String[] var10 = factoryImplementationNames;
int var11 = factoryImplementationNames.length;
for(int var12 = 0; var12 < var11; ++var12) {
String factoryImplementationName = var10[var12];
((List)result.computeIfAbsent(factoryTypeName, (key) -> {
return new ArrayList();
})).add(factoryImplementationName.trim());
}
}
}
result.replaceAll((factoryType, implementations) -> {
return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
});
cache.put(classLoader, result);
return result;
} catch (IOException var14) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var14);
}
}
}
private static <T> T instantiateFactory(String factoryImplementationName, Class<T> factoryType, ClassLoader classLoader) {
try {
Class<?> factoryImplementationClass = ClassUtils.forName(factoryImplementationName, classLoader);
if (!factoryType.isAssignableFrom(factoryImplementationClass)) {
throw new IllegalArgumentException("Class [" + factoryImplementationName + "] is not assignable to factory type [" + factoryType.getName() + "]");
} else {
return ReflectionUtils.accessibleConstructor(factoryImplementationClass, new Class[0]).newInstance();
//使用默认构造函数,实例化factoryImplementationClass
}
} catch (Throwable var4) {
throw new IllegalArgumentException("Unable to instantiate factory class [" + factoryImplementationName + "] for factory type [" + factoryType.getName() + "]", var4);
}
}
}
ConfigurationClassPostProcessor
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, ApplicationStartupAware, BeanClassLoaderAware, EnvironmentAware {
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList();
String[] candidateNames = registry.getBeanDefinitionNames();
String[] var4 = candidateNames;
int var5 = candidateNames.length;
for(int var6 = 0; var6 < var5; ++var6) {
String beanName = var4[var6];
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
} else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
if (!configCandidates.isEmpty()) {
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry)registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator)sbr.getSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator");
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet(configCandidates);
HashSet alreadyParsed = new HashSet(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
parser.parse(candidates); //解析配置类
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry());
}
this.reader.loadBeanDefinitions(configClasses);
//加载配置类信息
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> {
return String.valueOf(configClasses.size());
}).end();
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet();
Iterator var13 = alreadyParsed.iterator();
while(var13.hasNext()) {
ConfigurationClass configurationClass = (ConfigurationClass)var13.next();
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
String[] var24 = newCandidateNames;
int var25 = newCandidateNames.length;
for(int var15 = 0; var15 < var25; ++var15) {
String candidateName = var24[var15];
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && !alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
} while(!candidates.isEmpty());
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
((CachingMetadataReaderFactory)this.metadataReaderFactory).clearCache();
}
}
}
ConfigurationClassBeanDefinitionReader
class ConfigurationClassBeanDefinitionReader {
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
//加载类信息
ConfigurationClassBeanDefinitionReader.TrackedConditionEvaluator trackedConditionEvaluator = new ConfigurationClassBeanDefinitionReader.TrackedConditionEvaluator();
Iterator var3 = configurationModel.iterator();
while(var3.hasNext()) {
ConfigurationClass configClass = (ConfigurationClass)var3.next();
this.loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, ConfigurationClassBeanDefinitionReader.TrackedConditionEvaluator trackedConditionEvaluator) {
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
} else {
if (configClass.isImported()) {
this.registerBeanDefinitionForImportedConfigurationClass(configClass);
} //注册类信息(import导入的类)
Iterator var3 = configClass.getBeanMethods().iterator();
while(var3.hasNext()) {
BeanMethod beanMethod = (BeanMethod)var3.next();
this.loadBeanDefinitionsForBeanMethod(beanMethod);
} //注册类信息(@Bean)
this.loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
//加载注册ImportedResources导入的类
this.loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
//加载注册ImportBeanDefinitionRegistrar导入的类
}
}
********************
示例
*****************
pojo 层
Person
@Data
public class Person {
private String name="gtlx";
private Integer age=20;
}
*****************
service 层
HelloService
public interface HelloService {
void fun();
}
*****************
service.impl 层
HelloServiceImpl
public class HelloServiceImpl implements HelloService {
@Override
public void fun() {
System.out.println("hello");
}
}
HelloServiceImpl2
public class HelloServiceImpl2 implements HelloService {
@Override
public void fun() {
System.out.println("hello 2");
}
}
*****************
controller 层
HelloController
@RestController
public class HelloController {
@Resource
private Person person;
@Resource
private ApplicationContext applicationContext;
@Resource
private List<HelloService> helloServiceList;
@RequestMapping("/hello")
public String hello(){
System.out.println(person);
helloServiceList.forEach(HelloService::fun);
System.out.println();
System.out.println(applicationContext.getBean("com.example.demo.pojo.Person"));
((HelloService)applicationContext.getBean("com.example.demo.service.impl.HelloServiceImpl")).fun();
((HelloService)applicationContext.getBean("com.example.demo.service.impl.HelloServiceImpl2")).fun();
System.out.println();
SpringFactoriesLoader.loadFactoryNames(HelloService.class,null).forEach(System.out::println);
SpringFactoriesLoader.loadFactories(HelloService.class,null).forEach(System.out::println);
System.out.println("EnableAutoConfiguration size:"+SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,null).size());
return "success";
}
}
*****************
resources
新建目录META-INF
spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.demo.pojo.Person,\
com.example.demo.service.impl.HelloServiceImpl,\
com.example.demo.service.impl.HelloServiceImpl2
com.example.demo.service.HelloService=\
com.example.demo.service.impl.HelloServiceImpl,\
com.example.demo.service.impl.HelloServiceImpl2
********************
使用测试
localhost:8080/hello,控制台输出:
2021-09-25 10:22:42.646 INFO 3280 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2021-09-25 10:22:42.647 INFO 3280 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
Person(name=gtlx, age=20)
hello
hello 2
Person(name=gtlx, age=20)
hello
hello 2
com.example.demo.service.impl.HelloServiceImpl
com.example.demo.service.impl.HelloServiceImpl2
com.example.demo.service.impl.HelloServiceImpl@6e2d868f
com.example.demo.service.impl.HelloServiceImpl2@6c79885e
EnableAutoConfiguration size:134