此篇文章继续解析SpringApplication的run
方法具体代码如下:
public ConfigurableApplicationContext run(String... args) {
1.StopWatch stopWatch = new StopWatch();
2.stopWatch.start();
3.ConfigurableApplicationContext context = null;
4.Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
5.configureHeadlessProperty();
6.SpringApplicationRunListeners listeners = getRunListeners(args);
7.listeners.starting();
try {
8. ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
9. ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
10. configureIgnoreBeanInfo(environment);
11. Banner printedBanner = printBanner(environment);
12. context = createApplicationContext();
13. exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
14. prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
15. refreshContext(context);
16. afterRefresh(context, applicationArguments);
17. stopWatch.stop();
18. if (this.logStartupInfo) {
19. new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
20. listeners.started(context);
21. callRunners(context, applicationArguments);
}
catch (Throwable ex) {
22. handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
23. listeners.running(context);
}
catch (Throwable ex) {
24. handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
一共24行代码,本章主要解析12-13小节。
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
上述代码就是根据webApplicationType选择对应的contextClass ,然后根据class生产具体的applicationContext的子类AnnotationConfigServletWebServerApplicationContext。反射调用的构造函数
public AnnotationConfigServletWebServerApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
这就是spring容器
this.registry = registry;
处理@Conditional注解的
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
注册AnnotationAwareOrderComparator和ContextAnnotationAutowireCandidateResolver
前者是对注解的优先级进行排练,ContextAnnotationAutowireCandidateResolver是用来解析spring容器的自动注入的,还创建了一系列的注解后置处理器注册到spring容器中。
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
这就是spring容器
this.registry = registry;
if (useDefaultFilters) {
注册感兴趣的注解过滤器
registerDefaultFilters();
}
设置environment
setEnvironment(environment);
设置资源加载器
setResourceLoader(resourceLoader);
}
reader代表对注解Bean的处理器,scanner代表对classpath下面的bean进行扫描.
第13行代码主要是获取配置文件中SpringBootExceptionReporter的集合,主要就是reportException
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);创建的注解后置处理器有
- internalConfigurationAnnotationProcessor=ConfigurationClassPostProcessor
主要是用来处理@Configuration,我们可以手动配置该后置处理器也可以采用<context:annotation-config/>和<context:component-scan/>来注入此后置处理器
该后置处理器有最高优先权,任何在@Configuration注册definitions 的比其他的BeanFactoryPostProcessor的先执行
- 2.internalRequiredAnnotationProcessor=AutowiredAnnotationBeanPostProcessor
主要是处理@Autowired和@vAlue注解
- 3.internalRequiredAnnotationProcessor=RequiredAnnotationBeanPostProcessor
处理@Required
它检查带有@Required注解的所有Bean属性是否设置
我们的set方法必须是public才会检查(必须是set方法)
一般我们的属性该方法检测会在自动注入完属性之后再去看看还有那些属性未注册,然后查看其是否有@Required
- 4.internalCommonAnnotationProcessor=CommonAnnotationBeanPostProcessor
该后置处理器专门处理一大堆JSR-250的 annotations如:@PostConstruct和@PreDestroy和@Resource等
- 5.internalPersistenceAnnotationProcessor=PersistenceAnnotationBeanPostProcessor
JPA 方面注解
- 6.internalEventListenerProcessor =EventListenerMethodProcessor
处理@EventListener,该注解将一个方法标识为监听者 去监听application event
其会将被标识的方法转化成一个ApplicationListener
- 7.internalEventListenerFactory=DefaultEventListenerFactory
@EventListener依靠他去把方法转化为ApplicationListener
总结:
本篇文章主要介绍了创建spring容器 以及里面的两个关键属性reader和scanner的创建