接上文(),我们已经介绍了部分SpringApplication的启动过程,今天我们将继续讲解如何创建ApplicationContext的过程。
介绍
/**
* 这里我们可以自定义创建过程来覆盖缺省的Context
*/
protected ConfigurableApplicationContext createApplicationContext() {
return this.applicationContextFactory.create(this.webApplicationType);
}
Spring Boot创建ApplicationContext的过程主要为了后面准备和刷新Context,当然我们可以定制这个创建过程,这里我们先介绍Spring Boot的缺省逻辑
static class Factory implements ApplicationContextFactory {
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
// 创建并返回一个AnnotationConfigServletWebServerApplicationContext
return (webApplicationType != WebApplicationType.SERVLET) ? null
: new AnnotationConfigServletWebServerApplicationContext();
}
}
static class Factory implements ApplicationContextFactory {
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
// 创建并返回一个AnnotationConfigReactiveWebServerApplicationContext
return (webApplicationType != WebApplicationType.REACTIVE) ? null
: new AnnotationConfigReactiveWebServerApplicationContext();
}
}
这里会根据应用的类型创建不同的ApplicationContext
,下面我们将主要讲解servlet类型的ApplicationContext,关于Reactive Web Application的部分将在以后单独讲解。
/**
* 创建AnnotationConfigServletWebServerApplicationContext
*/
public AnnotationConfigServletWebServerApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
从上面的代码可以看出创建ApplicationContext的过程主要有两部分,我们将逐一讲解。
创建AnnotatedBeanDefinitionReader
/**
* 创建一个新的AnnotatedBeanDefinitionReader,如果这个registry是EnvironmentCapable的子类,
* 比如是一个ApplicationContext,那么Environment将从这个ApplicationContext继承
*/
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
这里的registry就是AnnotationConfigServletWebServerApplicationContext本身, 因为AnnotationConfigServletWebServerApplicationContext是新创建的,所有getOrCreateEnvironment(registry)返回的一定是一个新的StandardEnvironment。而将之前创建的Environment注入到这里是在准备ApplicationContext阶段进行的。
/**
* 用registry和environment来创建一个新的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;
// 推断ApplicationContext所需要的BeanFactory,Classloader等
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
// 注册annotation postprocessor
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
创建AnnotatedBeanDefinitionReader
实例的构造方法一共有2行逻辑, 首先会根据registry创建BeanFactory
,Classloader
等,然后给registry
也就是ApplicationContext
注册所有相关的annotation postprocessor,下面我们先来看看如果推断出BeanFactory
和各种loader的
创建ConditionEvaluator
public ConditionContextImpl(@Nullable BeanDefinitionRegistry registry,
@Nullable Environment environment, @Nullable ResourceLoader resourceLoader) {
this.registry = registry;
// 推断哪种beanFactory
this.beanFactory = deduceBeanFactory(registry);
// 推断哪种environment
this.environment = (environment != null ? environment : deduceEnvironment(registry));
// 推断哪种resourceLoader
this.resourceLoader = (resourceLoader != null ? resourceLoader : deduceResourceLoader(registry));
// 推断哪种classLoader
this.classLoader = deduceClassLoader(resourceLoader, this.beanFactory);
}
beanFactory
: 根据registry
的类型推断出哪种beanFactory
,前面我们已经提到registry
就是AnnotationConfigServletWebServerApplicationContext
,而AnnotationConfigServletWebServerApplicationContext
是ConfigurableApplicationContext
的子类,所以最后得到的是DefaultListableBeanFactory
environment
:前面我们已经得到了一个新的StandardEnvironment,这里直接设置 resourceLoader
:这里和environment
类似,因为AnnotationConfigServletWebServerApplicationContext
本身就是ResourceLoader的子类,所以返回的就是它本身classLoader
: 将返回beanFactory
上的beanClassLoader
注册annotation后处理器
下面是如何注册annotation postprocessor,整个过程看上去较为复杂,实际逻辑并不复杂,只是注册不同类型的postprocessor
/**
* 注册所有相关的注解后处理器annotation postprocessor
*/
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 返回registry上的DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
// 设置DependencyComparator
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
// 设置AutowireCandidateResolver
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
// 创建一个可以处理有@Configuration注解的类的postprocessor,并注册到RootBeanDefinition
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 创建一个可以处理有@Autowired注解的类的postprocessor,并注册到RootBeanDefinition
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 创建一个可以处理有一般类型注解的类的postprocessor,并注册到RootBeanDefinition
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 创建一个可以处理有@Persistence注解的类的postprocessor,并注册到RootBeanDefinition
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 创建一个可以处理eventlistener的postprocessor,并注册到RootBeanDefinition
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
// 创建一个可以处理有@Eventlistener注解的类的postprocessor,并注册到RootBeanDefinition
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
创建ClassPathBeanDefinitionScanner
创建类扫描器ClassPathBeanDefinitionScanner,ClassPathBeanDefinitionScanner会对指定路径下的所有class进行扫描,将符合条件的转成BeanDefinition并注册到ApplicationContext中,这部分会在以后的文章中讲解,下面我们先来看一下如何创建一个ClassPathBeanDefinitionScanner。
/**
* 创建一个新的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);
// 设置resourceLoader
setResourceLoader(resourceLoader);
}
注册缺省过滤器
首先我们会先注册一个缺省的过滤器Filter,缺省的Filter会检查所有有以下几种注解的类
- @Component
- @Repository
- @Service
- @Controller
- @ManagedBean
- @Named
protected void registerDefaultFilters() {
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
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.
}
}
`this.includeFilters.add(newAnnotationTypeFilter(Component.class));
这段代码看上去去只加了Component注解,实际上它会找到所有有Component注解的注解,如Repository,Service,Controller
设置Environment
这里Environment的作用是,当有条件注解或者有占位符注解的component类时,可以用Environment里的变量来替代
/**
* 设置Environment
*/
public void setEnvironment(Environment environment) {
Assert.notNull(environment, "Environment must not be null");
this.environment = environment;
this.conditionEvaluator = null;
}
设置ResourceLoader
设置ResourceLoader是为了后面处理需要加载各种properties里的变量时使用
public void setResourceLoader(@Nullable ResourceLoader resourceLoader) {
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
this.componentsIndex = CandidateComponentsIndexLoader.loadIndex(this.resourcePatternResolver.getClassLoader());
}
结语
我们已经讲完了所有创建ApplicationContext的步骤,这里其实是创建了一个AnnotationConfigServletWebServerApplicationContext,后续文章将继续讲解初始化SpringApplication过程中的其他步骤,包括准备,刷新Context和启动Runner的部分。