- 获取BeanDefinition 主源
- 推断应用类型
- ApplicationContext初始化器
- 监听器和事件
- 主类推断
文章目录- 构造方法解析
- 1.1 获取BeanDefinition 主源
- 1.2 推断应用类型
- 1.3 ApplicationContext初始化器
- 1.4 监听器和事件
- 1.5 主类推断
这里可以理解为获取一个ResourceLoader 用于获取BeanDefinition
然后断言主源是否存在
然后将主源添加到集合中, 这个集合为primarySources
集合用于后续解析获取到BeanDefinition
用于判断是SERVLET 还是 REACTIVE 还是 NONE
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
1.3 ApplicationContext初始化器
初始化进行增强
private ListgetBootstrapRegistryInitializersFromSpringFactories() { ArrayList initializers = new ArrayList<>(); getSpringFactoriesInstances(Bootstrapper.class).stream() .map((bootstrapper) -> ((BootstrapRegistryInitializer) bootstrapper::initialize)) .forEach(initializers::add); initializers.addAll(getSpringFactoriesInstances(BootstrapRegistryInitializer.class)); return initializers; }
springApplication.addInitializers(new ApplicationContextInitializer() { @Override public void initialize(ConfigurableApplicationContext applicationContext) { // context GenericApplicationContext context = (GenericApplicationContext) applicationContext; context.registerBean("bean1", Bean1.class); } });
在spring.factories下面的ApplicationContextInitializer加载类
spring-boot项目下
# Application Context Initializers org.springframework.context.ApplicationContextInitializer= org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer, org.springframework.boot.context.ContextIdApplicationContextInitializer, org.springframework.boot.context.config.DelegatingApplicationContextInitializer, org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer, org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
spring-boot-autoconfigure项目下
# Initializers org.springframework.context.ApplicationContextInitializer= org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer, org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
具体的加载方法为 getSpringFacotiesInstance()方法
privateCollection getSpringFactoriesInstances(Class type, Class>[] parameterTypes, Object... args) { ClassLoader classLoader = getClassLoader(); // Use names and ensure unique to protect against duplicates Set names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }
SpringFactoriesLoader.loadFactoryNames(type, classLoader)中具体查看加载文件的过程
loadSpringFactories()
通过 loadSpringFactories 方法我们看到把 spring.factories文件中的所有信息都加载到了内存中了,但是我们现在只需要加载 ApplicationContextInitializer类型的数据。
getOrDefault():
default V getOrDefault(Object key, V defaultValue) {
V v;
return (((v = get(key)) != null) || containsKey(key))
? v
: defaultValue;
}
然后会根据反射获取对应的实例对象。
getSpringFactoriesInstances方法就是帮我们定义在META-INF/spring.factories文件中的认为是ApplicationContextInitializer的值, 并通过反射获取实例对象, 然后将实例对象存储在initializers属性中。
注册监听器, 用于后面使用
要获取的 META-INF/spring.factories文件中定义ApplicationListener的值
加入到listeners 属性中。
1.5 主类推断判断main方法是哪个类
这里我利用反射调用这个方法
@SpringBootApplication
public class Main {
public static void main(String[] args)throws Exception{
SpringApplication app = new SpringApplication(Main.class);
app.run(args);
Method method = SpringApplication.class.getDeclaredMethod("deduceMainApplicationClass");
method.setAccessible(true);
System.out.println(method.invoke(app));
}
}
获取类名



