- 获取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 List<BootstrapRegistryInitializer> getBootstrapRegistryInitializersFromSpringFactories() {
ArrayList<BootstrapRegistryInitializer> 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<ConfigurableApplicationContext>() {
@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()方法
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> 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
属性中。
判断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));
}
}
获取类名
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)