prepareContext()方法解析
prepareContext,顾名思义就是准备上下文,这里内部执行了上下文的初始化器、通知SpringApplicationRunListener监听器到了各个阶段、设置beanFactory属性、解析主类(中间有一些特殊的配置类也能被加载,但是水比较浅,还没看到,就提一嘴)信息注册进BeanDefinition。主要还是在补充上下文的信息。
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
// 1.设置环境变量和上下文(这里准确的说,应该是补充上下文)
context.setEnvironment(environment);
postProcessApplicationContext(context);
// 2.遍历SpringApplication中搜集的initializers集合,依次执行initialize方法
// GenericTypeResolver.resolveTypeArgument(initializer.getClass(),ApplicationContextInitializer.class);
// 上面的方法用于获取类的泛型类型
applyInitializers(context);
// 3.通知运行时的listeners,执行到了prepared阶段了
listeners.contextPrepared(context);
// 4.关闭bootstrapContext上下文
// 内部最后是调用ApplicationListener#onApplicationEvent()通知监听器
bootstrapContext.close(context);
// 5.启动日志
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 6.注册args和banner到bean容器
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
// 7.设置beanFactory属性
if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
}
// 8.设置BeanFactory的后置处理器
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
// 9.Load the sources
// 获取程序的入口,一般是获取@SpringBootApplication注解修饰的含main方法的类,以及配置类或者@Configuration修饰的类
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
// 10.把source集合下的类,解析成BeanDefinition,默认情况下这步只会注册我们的启动类
load(context, sources.toArray(new Object[0]));
// 11.通知监听器,执行到context-loaded步骤了
listeners.contextLoaded(context);
}
applyInitializers()方法
applyInitializers() 方法,主要是执行在创建SpringApplication()方法时,加载ApplicationContextInitializer.class的实现类中的初始化方法
// SpringApplication类的构造方法
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
// 这里加载了ApplicationContextInitializer.class的实现类
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
// applyInitializers方法中调用它们的initialize(方法)
protected void applyInitializers(ConfigurableApplicationContext context) {
for (ApplicationContextInitializer initializer : getInitializers()) {
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
// 这些initialize有做初始化的,有给context对象set值的
initializer.initialize(context);
}
}
getAllSources()方法
这里说一下getAllSources()方法,内部有两个重要属性this.primarySources和this.sources,都是SpringApplication中的属性
public Set<Object> getAllSources() {
Set<Object> allSources = new LinkedHashSet<>();
if (!CollectionUtils.isEmpty(this.primarySources)) {
allSources.addAll(this.primarySources);
}
// 启动时加载默认为空
if (!CollectionUtils.isEmpty(this.sources)) {
allSources.addAll(this.sources);
}
return Collections.unmodifiableSet(allSources);
}
在Spring框架中,primarySources和sources是SpringApplication类中的两个属性,它们用于存储应用程序的入口类。这两个属性的类型都是Set<Class<?>>,即存储的是类的引用。
- primarySources属性用于存储应用程序的主入口类。在Spring Boot应用程序中,通常会有一个或多个主入口类,这些类使用@SpringBootApplication注解,并包含main方法。这些主入口类会被Spring Boot框架自动扫描和加载。
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// 创建SpringApplication时,会把你的主类,添加到primarySources
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
- sources属性用于存储应用程序的其他入口类。这些类可以是任何配置类,也可以是任何包含@Configuration注解的类。这些类会被Spring Boot框架加载,但不会作为主入口类。
load()方法
这里简单说一下load方法,这里会将主类组装成BeanDefinition,放入BeanDefinitionRegistry。
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
// getBeanDefinitionRegistry()方法内部很简单,直接把context进行了强转
BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
loader.load();
}
// 获取BeanDefinitionRegistry直接强转,说明我们传入的上下文,其实就包含了BeanDefinitionRegistry的实现
private BeanDefinitionRegistry getBeanDefinitionRegistry(ApplicationContext context) {
if (context instanceof BeanDefinitionRegistry) {
return (BeanDefinitionRegistry) context;
}
if (context instanceof AbstractApplicationContext) {
return (BeanDefinitionRegistry) ((AbstractApplicationContext) context).getBeanFactory();
}
throw new IllegalStateException("Could not locate BeanDefinitionRegistry");
}
// 创建BeanDefinitionLoader,其实就是一个赋值操作
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
Assert.notNull(registry, "Registry must not be null");
Assert.notEmpty(sources, "Sources must not be empty");
this.sources = sources;
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
this.xmlReader = (XML_ENABLED ? new XmlBeanDefinitionReader(registry) : null);
this.groovyReader = (isGroovyPresent() ? new GroovyBeanDefinitionReader(registry) : null);
this.scanner = new ClassPathBeanDefinitionScanner(registry);
this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
}
load内部最后会执行到doRegisterBean()方法,最终是把BeanDefinition注册到beanDefinitionMap属性中
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
//创建一个注解类型的通用BeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
//判断有没有condition条件,根据条件判断是否需要装载
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
//下面一大段都是给BeanDefinition内部的属性赋值
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
// 把BeanDefinition信息和beanName放入BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 根据代理模式生成对应的definitionHolder
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 注册beanDefinition到DefaultListableBeanFactory中的beanDefinitionMap属性中
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
结论
prepareContext()方法内部其实还是对ConfigurableApplicationContext的补充,以及一些初始化操作。实际做的,还是Springboot加载META-INF/spring.factories中的实现类,要提前放入ConfigurableApplicationContext上下文中,为后续Spring去执行refresh方法创建bean做准备。
- 给ConfigurableApplicationContext赋值环境变量
- 给ConfigurableApplicationContext内部的属性赋值
- 把ConfigurableApplicationContext传给初始化类,执行内部的初始化方法
- 注册一些后置处理器到ConfigurableApplicationContext
- 解析启动类信息,包装成BeanDefinition
- 通知监听器,到了Springboot启动到了prepare和context-loaded步骤了