1、ApplicationContextInitializer初始化器解析
1.3、初始化器解析
1) 在上下文刷新即refresh方法前调用2) 用来编码设置一些属性变量,通常用在web环境中
3) 可以通过order接口进行排序
1.4、 添加原理分析
1) 定义在spring.factories文件中被SpringFactoriesLoader发现注册2) SpringApplication初始化完毕后手动添加
3) 定义成环境变量被DelegatingApplicationContextInitializer发现注册
1.4.1、方式1分析
方式1)代码分析:定义在spring.factories文件中被SpringFactoriesLoader发现注册
@SpringBootApplicationpublic class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 到这一步从spring.factories中加载ApplicationContextInitializer.class的实现类
setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection)getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, new Class<?>[] {});
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
// 1) 从spring.factories中加载ApplicationContextInitializer.class的实现类
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 2) 实例化步骤1中得到的实现类
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// 3) 根据order注解进行排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
// 1) 从spring.factories中加载ApplicationContextInitializer.class的实现类Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
// org.springframework.context.ApplicationContextInitializer
String factoryClassName = factoryClass.getName();
// 获得一个Map,map形如<key,List<String>>形式,后面getOrDefault是获取
// org.springframework.context.ApplicationContextInitializer对应的实现类集合
return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
// 带缓存功能,从各个jar包的META-INF/spring.factories文件中加载实现类,一个key可能包含多个实现
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
// 缓存中有直接返回
return result;
}
try {
// FACTORIES_RESOURCE_LOCATION值是META-INF/spring.factories
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()) {
// 获取key
String factoryClassName = ((String) entry.getKey()).trim();
// 将value逗号分隔,获得各个具体的实现类
for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
// 放入result中
result.add(factoryClassName, factoryName.trim());
}
}
}
cache.put(classLoader, result);
// 返回的result见下图
return result;
}
}
// 2) 实例化步骤1中得到的实现类List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader,
Object[] args, Set<String> names) {
List<T> instances = new ArrayList<>(names.size());
for (String name : names) {
try {
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
// 判断instanceClass是否是ApplicationContextInitializer的实现类
Assert.isAssignable(type, instanceClass);
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
T instance = (T) BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
}
}
return instances;
}
// 3) 根据order注解进行排序AnnotationAwareOrderComparator.sort(instances);
public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();
public static void sort(List<?> list) {
if (list.size() > 1) {
list.sort(INSTANCE);
}
}
1.4.2、方式2分析
方式2)代码分析:手动添加
@SpringBootApplicationpublic class SpringbootApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(SpringbootApplication.class);
springApplication.addInitializers(new SecondInitializer());
springApplication.run(args);
}
}
public void addInitializers(ApplicationContextInitializer<?>... initializers) {
// 方式1最终也是放入到了SpringApplication的initializers集合中
this.initializers.addAll(Arrays.asList(initializers));
}
1.4.3、方式3分析
方式3)代码分析:在application.properties中配置,通过DelegatingApplicationContextInitializer注入
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = getClassLoader();
// 这边加载之后默认有7个实现类,有一个是DelegatingApplicationContextInitializer
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// 排完序后见下图,发现DelegatingApplicationContextInitializer在最前
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) { // 方式1中分析的是SpringApplicatin的构造函数,构造函数完了之后已经加载了spring.factories的
// class到SpringApplication的initializers集合中,接着运行run函数
return new SpringApplication(primarySources).run(args);
}
// 核心代码,删除了部分代码,只分析与此有关的步骤public ConfigurableApplicationContext run(String... args) {
try {
context = createApplicationContext();
// 走这一步
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
}
return context;
}
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments,
Banner printedBanner) {
context.setEnvironment(environment);
postProcessApplicationContext(context);
// 走这一步,调用各个initializers的initialize方法
applyInitializers(context);
// 删除部分代码
}
protected void applyInitializers(ConfigurableApplicationContext context) {
// 遍历每个initializers,调用其initialize方法
for (ApplicationContextInitializer initializer : getInitializers()) {
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
// 调用initialize方法,第一个调用的就是DelegatingApplicationContextInitializer
initializer.initialize(context);
}
}
// DelegatingApplicationContextInitializer的initialize方法public void initialize(ConfigurableApplicationContext context) {
ConfigurableEnvironment environment = context.getEnvironment();
List<Class<?>> initializerClasses = getInitializerClasses(environment);
if (!initializerClasses.isEmpty()) {
applyInitializerClasses(context, initializerClasses);
}
}
private List<Class<?>> getInitializerClasses(ConfigurableEnvironment env) {
// PROPERTY_NAME = "context.initializer.classes";
// classNames这里是com.lwh.springboot.initializer.ThirdInitializer
String classNames = env.getProperty(PROPERTY_NAME);
List<Class<?>> classes = new ArrayList<>();
if (StringUtils.hasLength(classNames)) {
for (String className : StringUtils.tokenizeToStringArray(classNames, ",")) {
classes.add(getInitializerClass(className));
}
}
return classes;
}
private void applyInitializerClasses(ConfigurableApplicationContext context,
List<Class<?>> initializerClasses) {
Class<?> contextClass = context.getClass();
List<ApplicationContextInitializer<?>> initializers = new ArrayList<>();
// 实例化Initializer对象
for (Class<?> initializerClass : initializerClasses) {
initializers.add(instantiateInitializer(contextClass, initializerClass));
}
// 调用initialize方法
applyInitializers(context, initializers);
}
以上是 1、ApplicationContextInitializer初始化器解析 的全部内容, 来源链接: utcz.com/z/513537.html