ConfigurationClassPostProcessor作为SpringBoot自动配置原理的核心类,其加载流程是怎么样的呢?
一、ConfigurationClassPostProcessor类信息的注册
(1)创建应用上下文(也就是Spring容器)
public class SpringApplication {
public ConfigurableApplicationContext run(String... args) {
......
// 创建Spring容器
context = createApplicationContext();
......
}
}
(2)根据Web应用类型创建应用上下文(可以看一下ConfigurableApplicationContext该类的继承体系,就知道为什么它就是Spring容器了)
public class SpringApplication {
protected ConfigurableApplicationContext createApplicationContext() {
return this.applicationContextFactory.create(this.webApplicationType);
}
}
根据Web应用类型创建应用上下文(此处采用了工厂模式),那么ApplicationContextFactory是怎么是实例化的呢,如下:
public class SpringApplication {
private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT;
}
SpringApplication实例化过程中,实例化了一个ApplicationContextFactory对象,赋给成员变量applicationContextFactory,而ApplicationContextFactory是一个函数式接口,我们进去看下细节:
@FunctionalInterface
public interface ApplicationContextFactory {
ApplicationContextFactory DEFAULT = (webApplicationType) -> {
try {
for (ApplicationContextFactory candidate : SpringFactoriesLoader
.loadFactories(ApplicationContextFactory.class, ApplicationContextFactory.class.getClassLoader())) {
ConfigurableApplicationContext context = candidate.create(webApplicationType);
if (context != null) {
return context;
}
}
return new AnnotationConfigApplicationContext();
}
catch (Exception ex) {
throw new IllegalStateException("Unable create a default ApplicationContext instance, "
+ "you may need a custom ApplicationContextFactory", ex);
}
};
ConfigurableApplicationContext create(WebApplicationType webApplicationType);
}
DEFAULT是ApplicationContextFactory函数式接口的静态常量,采用Lambda表达式创建一个应用上下文工厂。那么应用上下文工厂的元数据是怎么加载的呢?核心实现就是SpringFactoriesLoader,该类的静态常量cache中保存了SpringBoot启动时,从META-INF/spring.factories文件中解析的ApplicationContextFactory映射的类信息,如下:
# Application Context Factories
org.springframework.boot.ApplicationContextFactory=\
org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext.Factory,\
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext.Factory
该映射信息的spring.factories文件位于spring-boot-x.x.xx.jar的META-INF目录下。
DEFAULT的Lambda表达式内部实现中,SpringFactoriesLoader加载了应用上下文工厂的实例(AnnotationConfigServletWebServerApplicationContext中内部类Factory对象和
AnnotationConfigReactiveWebServerApplicationContext中内部类Factory对象)集合,分别看下这两个Factory对象:
public class AnnotationConfigReactiveWebServerApplicationContext extends ReactiveWebServerApplicationContext
implements AnnotationConfigRegistry {、
......
static class Factory implements ApplicationContextFactory {
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
return (webApplicationType != WebApplicationType.REACTIVE) ? null
: new AnnotationConfigReactiveWebServerApplicationContext();
}
}
}
public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext
implements AnnotationConfigRegistry {
......
static class Factory implements ApplicationContextFactory {
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
return (webApplicationType != WebApplicationType.SERVLET) ? null
: new AnnotationConfigServletWebServerApplicationContext();
}
}
}
可以看到create(WebApplicationType webApplicationType)中,根据WebApplicationType创建了对应的Web应用上下文实例。
因为在Springboot启动的时候,确定了WebApplicationType(枚举)为SERVIET类型(那么怎么确定SERVLET类型的呢,会有另外的文章专门介绍,这里先不讨论),所以最后创建的Web应用上下文是AnnotationConfigServletWebServerApplicationContext的实例。
那么到此,为什么要介绍Web应用上下文(AnnotationConfigServletWebServerApplicationContext)的实例化流程呢,因为在该对象的实例化的构造方法中,有ConfigurationClassPostProcessor类信息注册的实现细节。
public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext
implements AnnotationConfigRegistry {
......
public AnnotationConfigServletWebServerApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
......
}
重点this.reader = new AnnotatedBeanDefinitionReader(this);
public class AnnotatedBeanDefinitionReader {
......
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
......
}
继续看this(registry, getOrCreateEnvironment(registry));
public class 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);
public abstract class AnnotationConfigUtils {
......
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, null);
}
......
}
public abstract class AnnotationConfigUtils {
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
......
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
......
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));
}
}
......
}
可以看到将ConfigurationClassPostProcessor.class封装成了RootBeanDefinition,然后将RootBeanDefinition注册入Web应用上下文(registry)。
public abstract class AnnotationConfigUtils {
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
......
// 将bean的定义信息注册入应用上下文registry中
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
......
}
该方法中,beanName就是“org.springframework.context.annotation.internalConfigurationAnnotationProcessor”。而internalConfigurationAnnotationProcessor这个类是不存的,只是Spring将internalConfigurationAnnotationProcessor与ConfigurationClassPostProcessor.class做了映射,封装成RootBeanDefinition对象注册入Web应用上下文。
ConfigurationClassPostProcessor类信息在容器中的注册完成。