“spring.beaninfo.ignore”,值为“true”表示跳过对BeanInfo类的搜索(通常用于首先没有为应用程序中的bean定义此类的情况)。
考虑到所有BeanInfo元数据类,默认值为“false”,例如标准的Introspector.getBeanInfo(Class)调用。
如果您遇到对不存在的BeanInfo类重复的ClassLoader访问,请考虑将此标志切换为“true”,以防此类访问在启动或延迟加载时很昂贵。
SpringApplication的run方法
public ConfigurableApplicationContext run(String... args) {
// 跑表,记录开始和结束时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 一般是在程序开始激活headless模式,告诉程序,现在你要工作在Headless mode下,就不要指望硬件帮忙了,你得自力更生,依靠系统的计算能力模拟出这些特性来
configureHeadlessProperty();
// META-INF/spring.factories文件中获取SpringApplicationRunListener接口的实现类。
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(); // SpringApplicationRunListener监听器开启监听
try {
// 保存args参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备环境变量, 读取application.properties文件中的环境变量
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 跳过对不存在的BeanInfo类的搜索
configureIgnoreBeanInfo(environment);
//
Banner printedBanner = printBanner(environment);
// 创建ApplicationContext, 即创建bean工厂
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 将environment, listeners, applicationArguments, printedBanner等全部注册到bean工厂
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// IoC容器开始创建bean实例
refreshContext(context);
// IoC容器完成后
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
// 回调 ApplicationRunner,CommandLineRunner
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
1、 SpringApplicationRunListener 监听器
Listener for the {@link SpringApplication} {@code run} method.
SpringApplicationRunListener用来监听SpringApplication的run方法;
用来回调CommandLineRunner,ApplicationRunner 对象实例的
2、根据key类型加载 META-INF/spring.factories 文件中的类。
org/springframework/boot/spring-boot/2.1.4.RELEASE/spring-boot-2.1.4.RELEASE.jar!/META-INF/spring.factories
SpringFactoriesLoader.loadFactoryNames(type, classLoader)
根据key类型加载 META-INF/spring.factories 文件中的类。
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader; // null
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//// 根据key类型加载 META-INF/spring.factories 文件中的ApplicationContextInitializer类。
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//根据key类型加载 META-INF/spring.factories 文件中的ApplicationListener类。
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
image.png
3、SpringApplication 加载META-INF/spring.factories文件中执行类型的key的过程
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader(); // 获取类加载器,默认当前线程的类加载器
// Use names and ensure unique to protect against duplicates
// SpringFactoriesLoader根据type类型(key类型)加载加载spring.factories文件的类
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 对获取到的类创建对象实例
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// 根据@Order或@Priority对对象实例排序
AnnotationAwareOrderComparator.sort(instances);
return instances;//返回对象实例
}
自动配置启动流程
ConfigurationClassPostProcessor
ConfigurationClassParser
SpringApplication执行run方法
run方法执行 AbstractApplicationContext.refresh方法
在refresh方法中, 实现了对ConfigurationClassParser的调用。
AbstractApplicationContext.refresh方法
AbstractApplicationContext.refresh
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
image.png image.pngConfigurationClassPostProcessor
image.png image.png image.png image.pngConfigurationClassParser
image.png
AnnotationConfigReactiveWebServerApplicationContext
创建是AnnotationConfigReactiveWebServerApplicationContext
image.pngBeanFactoryPostProcessor可以与bean定义交互并修改它们,但不能与bean实例交互。这样做可能会导致过早的bean实例化,违反容器并导致意外的副作用。如果需要bean实例交互,请考虑实现beanpstprocessor。
image.png image.png image.png image.png
网友评论