一、ApplicationContext在Spring Boot中是如何创建的?
1. SpringApplication
ApplicationContextFactory有三个实现类,分别是AnnotationConfigReactiveWebServerApplicationContext.Factory
、AnnotationConfigServletWebServerApplicationContext.Factory
、DefaultApplicationContextFactory。
public ConfigurableApplicationContext run(String... args) {...// 创建ApplicationContextcontext = createApplicationContext();...
}// 调用DefaultApplicationContextFactory的create
protected ConfigurableApplicationContext createApplicationContext() {return this.applicationContextFactory.create(this.webApplicationType);
}
2. DefaultApplicationContextFactory
下面有一点代码SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class, getClass().getClassLoader()),是从org.springframework.boot
的META-INF/spring.factories
寻找ApplicationContextFactory的实现类,也就是AnnotationConfigReactiveWebServerApplicationContext.Factory和AnnotationConfigServletWebServerApplicationContext.Factory。
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {try {return getFromSpringFactories(webApplicationType, ApplicationContextFactory::create,AnnotationConfigApplicationContext::new);}catch (Exception ex) {throw new IllegalStateException("Unable create a default ApplicationContext instance, "+ "you may need a custom ApplicationContextFactory", ex);}
}private <T> T getFromSpringFactories(WebApplicationType webApplicationType,BiFunction<ApplicationContextFactory, WebApplicationType, T> action, Supplier<T> defaultResult) {for (ApplicationContextFactory candidate : SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class,getClass().getClassLoader())) {// 判断应用属于三种NONE、SERVLET、REACTIVE类型中的哪种类型,实例化对应类型的ApplicationContenxt。T result = action.apply(candidate, webApplicationType);if (result != null) {return result;}}// 创建AnnotationConfigApplicationContextreturn (defaultResult != null) ? defaultResult.get() : null;
}
二、AnnotationConfigServletWebServerApplicationContext构造函数做了什么事情?
public AnnotationConfigServletWebServerApplicationContext() {this.reader = new AnnotatedBeanDefinitionReader(this);this.scanner = new ClassPathBeanDefinitionScanner(this);
}
1. AnnotatedBeanDefinitionReader
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");Assert.notNull(environment, "Environment must not be null");this.registry = registry;this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
注册了以下6个bean。
- org.springframework.context.annotation.internalConfigurationAnnotationProcessor
- org.springframework.context.annotation.internalAutowiredAnnotationProcessor
- org.springframework.context.annotation.internalCommonAnnotationProcessor
- org.springframework.context.annotation.internalPersistenceAnnotationProcessor
- org.springframework.context.event.internalEventListenerProcessor
- org.springframework.context.event.internalEventListenerFactory
2. ClassPathBeanDefinitionScanner
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,Environment environment, @Nullable ResourceLoader resourceLoader) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");this.registry = registry;if (useDefaultFilters) {registerDefaultFilters();}setEnvironment(environment);setResourceLoader(resourceLoader);
}
registerDefaultFilters
注册了以下的过滤器
protected void registerDefaultFilters() {this.includeFilters.add(new AnnotationTypeFilter(Component.class));// 这个ClassLoader是干什么的???ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();try {this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.}try {this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-330 API not available - simply skip.}
}
- Component.class
- javax.annotation.ManagedBean
- javax.inject.Named