在从nacos-spring-boot-project角度全面看Springboot Starter中,我们提到过从spring.factories中找出key为XXX的类。比如org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的NacosConfigAutoConfiguration
中会在spring.factories文件中找出key为EnableAutoConfiguration对应的值。这些类都是自动化配置类:
// 这个spring.factories文件在spring-boot-autoconfigure模块的 META-INF/spring.factories中
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.alibaba.boot.nacos.config.autoconfigure.NacosConfigAutoConfiguration
Spring Framework内部使用一种工厂加载机制(Factory Loading Mechanism)。这种机制使用SpringFactoriesLoader完成,SpringFactoriesLoader使用loadFactories方法加载并实例化从META-INF目录里的spring.factories文件出来的工厂,这些spring.factories文件都是从classpath里的jar包里找出来的。
spring.factories文件是以Java的Properties格式存在,key是接口或抽象类的全名、value是以逗号 " , " 分隔的实现类,比如:
example.MyService=example.MyServiceImpl1,example.MyServiceImpl2
其中example.MyService是接口的全名,example.MyServiceImpl1和example.MyServiceImpl2是这个接口的两种实现。
可通过SpringFactoriesLoader完成:
List classes = SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class, this.getClass().getClassLoader());
classes.forEach(clazz -> {
System.out.println("==== " + clazz);
});
总结:
工厂加载机制是Spring内部提供的一个约定俗成的加载方式。只需要在模块的META-INF目录下定义Properties格式的spring.factories文件,这个Properties格式的文件中的key是接口或抽象类的全名,value是以逗号 " , " 分隔的实现类。
SpringBoot中的autoconfigure模块中的spring.factories就存在于META-INF目录下:
├── META-INF
│ ├── MANIFEST.MF
│ ├── additional-spring-configuration-metadata.json
│ ├── maven
│ │ └── org.springframework.boot
│ │ └── spring-boot-autoconfigure
│ │ ├── pom.properties
│ │ └── pom.xml
│ ├── spring-configuration-metadata.json
│ └── spring.factories
├── org
│ └── springframework
│ └── boot
│ └── autoconfigure
│ ├── AbstractDependsOnBeanFactoryPostProcessor.class
....
而且也定义了一些配置,比如自动化配置信息:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=...
应用初始化器:
org.springframework.context.ApplicationContextInitializer=...
应用监听器:
org.springframework.context.ApplicationListener=...
模板可用提供器:
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=...
我们只需要遵守这个机制并在对应的文件中写出需要加载的接口和实例即可,或者自己使用SpringFactoriesLoader实现加载。
参考:SpringBoot源码分析之工厂加载机制