-- 以下内容均基于2.1.8.RELEASE版本
紧接着上一篇(二)SpringBoot启动过程的分析-环境信息准备,本文将分析环境准备完毕之后的下一步操作:ApplicationContext的创建。
// SpringApplication.java
ConfigurableApplicationContext context = createApplicationContext();
protected ConfigurableApplicationContext createApplicationContext() {
// ①
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
// ②
contextClass = Class.forName(DEFAULT_SERVLET_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);
}
创建ApplicationContext时可以指定需要创建的上下文类型,默认是根据当前应用类型来创建。在SpringApplication.java中指定了几种默认类型,他们分别是默认的非Web应用上下文容器、默认的Web应用上下文容器和响应式Web上下文容器
public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context." + "annotation.AnnotationConfigApplicationContext";
public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot." + "web.servlet.context.AnnotationConfigServletWebServerApplicationContext";
public static final String DEFAULT_REACTIVE_WEB_CONTEXT_CLASS = "org.springframework." + "boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext";
① - 是否有指定的ApplicationContext,若有直接实例化
② - 实例化Web应用上下文容器
③ - 实例化响应式Web应用上下文容器
④ - 实例化非Web应用上下文容器
⑤ - 使用无参构造函数对指定的上下文容器进行实例化
对于常规的以SpringBoot开发的web应用来说,AnnotationConfigServletWebServerApplicationContext将会是默认的上下文容器。它可以解析@Configuration等JSR-330定义的注解,查看它的包路径,可以看到,它是属于SpringBoot下的上下文容器。
public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
private final Set<Class<?>> annotatedClasses = new LinkedHashSet<>();
private String[] basePackages;
public AnnotationConfigServletWebServerApplicationContext() {
// ①
this.reader = new AnnotatedBeanDefinitionReader(this);
// ②
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
}
① - 构造AnnotatedBeanDefinitionReader,传入当前对象作为Bean注册器
② - 构造ClassPathBeanDefinitionScanner,传入当前对象作为Bean注册器
它内部的无参构造方法就干了两件事:初始化reader和scanner。他们两个的存在使当前的上下文容器支持以带有@Configuration注解的类作为加载Bean入口,也支持以指定的basePackage来作为加载Bean的入口,同时还支持注解的过滤。
用编程方式注册带注解的Bean到容器中,也就是基于注解配置的Bean的注册。
public class AnnotatedBeanDefinitionReader {
// ①
private final BeanDefinitionRegistry registry;
// ②
private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
// ③
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
// ④
private ConditionEvaluator conditionEvaluator;
// ⑤
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
// ...省略部分代码
}
① - BeanDefinition注册器
② - BeanName生成器
③ - Bean的作用域元数据解析器
④ - 条件注解评估器,用于判断是否跳过被条件注解修饰的类的加载
⑤ - 通过Bean注册器来构造Reader
在初始化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);
}
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, null);
}
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
// ①
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
// ②
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
// ③
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
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));
}
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));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
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));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
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));
}
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));
}
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;
}
① - 给BeanFactory添加AnnotationAwareOrderComparator,用于处理Bean的排序
② - 给BeanFactory添加ContextAnnotationAutowireCandidateResolver,用于处理@Lazy注解和@Qualifier注解
③ - 注册指定的类到容器
SpringBoot默认优先注册了以下PostProcessor类,并以不同的名称来称呼这些类:
左边的为BeanDefinition的名称,右边为对应的类,名称的前缀都统一是org.springframework.context.annotation
由Spring内部管理的用于处理配置注解的处理器
internalConfigurationAnnotationProcessor -> ConfigurationClassPostProcessor.class由Spring内部管理的用于处理自动装配注解的处理器
internalAutowiredAnnotationProcessor -> AutowiredAnnotationBeanPostProcessor.class由Spring内部管理的用于处理JSR-250注解的处理器
internalCommonAnnotationProcessor -> CommonAnnotationBeanPostProcessor.class由Spring内部管理的用于处理JPA注解的处理器
internalPersistenceAnnotationProcessor -> PersistenceAnnotationBeanPostProcessor.class由Spring内部管理的用于处理@EventListener注解的处理器
internalEventListenerProcessor -> EventListenerMethodProcessor.class由Spring内部管理的用于指定EventListenerFactory默认实现的类
internalEventListenerFactory -> DefaultEventListenerFactory.class
其实看到这里就明白许多,单纯的就是Spring固定了一些类要首先注册进去容器,也就是在处理注解的Reader准备完毕的时候,它已经准备好了一些后续要使用的类,他们用于在不同阶段来处理不同的事情。至于注册的这些类分别可以完成什么工作,将在他们真正开始执行的时候再进行分析。至此AnnotatedBeanDefinitionReader的初始化完成了。
和上面的Reader不同的是它用于扫描类路径上的Bean,通过给定的basePackage路径来扫描类。它可以使用可配置的过滤器来检测候选类,已确定他们将是否被加载。默认的过滤器包括Spring框架的@Component、@Controller、@Service、@Repository
// 构造方法一
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
this(registry, true);
}
// 构造方法二
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}
// 构造方法三
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment) {
this(registry, useDefaultFilters, environment,
(registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
}
// 构造方法四
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, @Nullable ResourceLoader resourceLoader) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
// 使用默认过滤器,从构造方法一直接传入true,代表它是默认的。
if (useDefaultFilters) {
// 注册默认过滤器
registerDefaultFilters();
}
// 设置环境对象和资源加载器
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
通过多个重载的构造方法来构造ClassPathBeanDefinitionScanner对象。最后一个实际使用的构造方法传入了类注册器、是否使用默认过滤器、环境对象、资源加载器。若传入的是一个普通的BeanDefinitionRegistry(实现了BeanDefinitionRegistry接口但没有实现ResourceLoader接口的类)那么默认的资源加载器将会是org.springframework.core.io.support.PathMatchingResourcePatternResolver.
为@Component注册过滤器, 还会隐式的注册@Controller、@Service、@Repository。为何说是隐式的呢?查看这几个注解便知。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
@AliasFor(annotation = Component.class)
String value() default "";
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
@AliasFor(annotation = Component.class)
String value() default "";
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
@AliasFor(annotation = Component.class)
String value() default "";
}
他同时使用了@Component注解,并将别名设置为Component.class
// ClassPathScanningCandidateComponentProvider.java
protected void registerDefaultFilters() {
// 新增Component注解过滤器(包含Controller、Service、Repository)
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
// 如果可用的话,支持JSR-250的ManagedBean注解过滤器
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 {
// 如果可用的话,支持JSR-330支持的Named注解过滤器
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.
}
}
在上下文容器创建完毕且未刷新的情况下,内部已经优先注册了一批PostProcessor,毫无疑问,他们将会在容器接下来的操作中扮演重要角色。这里只需要理解容器在程序运行的不同阶段会有不同的执行逻辑。大概知晓它在创建的时候做了什么,在后续文章中会逐步分析。
(三)SpringBoot启动过程的分析-创建应用程序上下文
原文:https://www.cnblogs.com/lukama/p/14525282.html