https://www.cnblogs.com/linlf03/p/12269834.html
https://www.bilibili.com/video/BV12C4y1s7dR?p=8
实现初始化
实现一
实现ApplicationContextInitializer接口
spring.factories内填写接口实现
key值为org.springframework.context.ApplicationContextInitializer
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import java.util.HashMap;
import java.util.Map;
@Order(1)
public class FirstInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
ConfigurableEnvironment environment = configurableApplicationContext.getEnvironment();
Map<String, Object> map = new HashMap<>();
map.put("initializer1", "test1");
MapPropertySource firstInitializer = new MapPropertySource("firstInitializer", map);
environment.getPropertySources().addLast(firstInitializer);
System.out.println("run firstInitializer");
}
}
META-INF/spring.factories
org.springframework.context.ApplicationContextInitializer=xxxxx
import com.java.study.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@Autowired
private TestService testService;
@RequestMapping("/test")
public String test(){
return testService.test();
}
}
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
@Service
public class TestService implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public String test() {
return applicationContext.getEnvironment().getProperty("initializer1");
}
}
实现二
实现ApplicationContextInitialize接口
SpringApplication类初识后设置进去
@SpringBootApplication
public class StudyApplication {
public static void main(String[] args) {
//SpringApplication.run(StudyApplication.class, args);
SpringApplication springApplication = new SpringApplication(StudyApplication.class);
springApplication.addInitializers(new SecondInitializer());
springApplication.run(args);
}
}
实现三
实现ApplicationContextInitialize接口
application.properties内填写接口实现
key值为context.initializer.classes
context.initializer.classes=com.java.study.initializer.ThirdInitializer
Order值越小越先执行
application.properties中定义的优先于其他方式
SpringFactoriesLoader
-
General purpose factory loading mechanism for internal use within the framework.
-
{@linkplain #loadFactories loads} and instantiates* factories of a given type from {@value #FACTORIES_RESOURCE_LOCATION} files which* may be present in multiple JAR files in the classpath.
-
file must be in {@link Properties} format, where the key is the fully qualified* name of the interface or abstract class, and the value is a comma-separated list of* implementation class names.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tbwQL6qV-1603852638524)(en-resource://database/3527:0)]
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
//AppClassLoader
ClassLoader classLoader = this.getClassLoader();
Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WMuKxcGp-1603852638526)(en-resource://database/3525:0)]
先从缓存中读取
缓存没有,从所有jar包下"META-INF/spring.factories"读取
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
if (result != null) {
return result;
} else {
try {
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
LinkedMultiValueMap result = new LinkedMultiValueMap();
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[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
int var10 = var9.length;
for(int var11 = 0; var11 < var10; ++var11) {
String factoryImplementationName = var9[var11];
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
} catch (IOException var13) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
}
}
}
调用流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GoZ304KB-1603852638527)(en-resource://database/3529:0)]
public class DelegatingApplicationContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
// NOTE: Similar to org.springframework.web.context.ContextLoader
private static final String PROPERTY_NAME = "context.initializer.classes";
private int order = 0;
@Override
public void initialize(ConfigurableApplicationContext context) {
ConfigurableEnvironment environment = context.getEnvironment();
List<Class<?>> initializerClasses = getInitializerClasses(environment);
if (!initializerClasses.isEmpty()) {
applyInitializerClasses(context, initializerClasses);
}
}
}