前言:springBoot的版本是 2.2.4.RELEASE
一、入口
/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
//主要看这个方法,初始化应用上下文
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
问题切入:为什么叫做上下文对象呢?上下文对象,就是当前应用环境下的一个集合
初始化(创建)上下文对象主要看上面注释那行,即:
context = createApplicationContext();
接着看下 createApplicationContext() 这个方法的实现
截图:
代码:
/**
* Strategy method used to create the {@link ApplicationContext}. By default this
* method will respect any explicitly set application context or application context
* class before falling back to a suitable default.
* @return the application context (not yet refreshed)
* @see #setApplicationContextClass(Class)
*/
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
// 创建上下文对象 AnnotationConfigServletWebServerApplicationContext 进行实例化的过程中,此时 ioc 容器也会被创建
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);
}
}
//创建 AnnotationConfigServletWebServerApplicationContext 对象的无参构造
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
接着看下AnnotationConfigServletWebServerApplicationContext 这个对象的继承关系
从继承关系上面看继承关系比较深,同时可以看到 GenericApplicationContext(通用上下文对象),上面实例化AnnotationConfigServletWebServerApplicationContext的时候就是从该对象的无参构造方法开始的,我们就从AnnotationConfigServletWebServerApplicationContext对象的无参构造方法从代码上面看一下代码逻辑,注意:子类实例化的时候先实例化父类的构造方法
截图如下:
1、AnnotationConfigServletWebServerApplicationContext 的无参构造【注解配置Servlet Web服务器应用程序上下文】
2、ServletWebServerApplicationContext 的无参构造【Servlet Web服务器应用程序上下文】
==> 这一步啥事没做
3、GenericWebApplicationContext 的无参构造【通用Web应用程序上下文】
==> 这个方法实例化的时候继承了父类
4、GenericApplicationContext 的无参构造【通用应用程序上下文】
==> 这里直接new一个 DefaultListableBeanFactory 对象,这个对象就是IOC容器最开始的样子,
这里其实是已经创建了 bean 工厂, DefaultListableBeanFactory 这个类里面有一个beanDefinitionMap,就是用来存放bean对象的。
二、AnnotationConfigServletWebServerApplicationContext 无参构造的两个重要方法
截图:
代码:
/**
* Create a new {@link AnnotationConfigServletWebServerApplicationContext} that needs
* to be populated through {@link #register} calls and then manually
* {@linkplain #refresh refreshed}.
*/
public AnnotationConfigServletWebServerApplicationContext() {
//创建一个读取注解的Bean定义读取器
//什么是 Bean 定义?BeanDefinition 完成了 spring 内部 Bean 的 BeanDefinition 的注册(主要是后置处理器)
this.reader = new AnnotatedBeanDefinitionReader(this);
//创建 BeanDefinition 扫描器,可以用来扫描包或者类,继而转换为 bd,
//spring 默认的扫描器其实不是这个 scanner 对象,而是在后面自己又重新 new 了一个 ClassPathBeanDefinitionScanner
//spring 在执行工程后置器 ConfigurationClassPostProcessor 时,去扫描包时会 new
//这里 scanner 仅仅是为了 程序员可以手动调用 AnnotationConfigApplicationContext 对象的 scanner方法
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
2.1 AnnotatedBeanDefinitionReader 构造方法
在看这个方法之前,我们先打个断点,然后看下this里面的 beanDefinitionMap 里面是否有有值,即IOC容器中是否有bean对象,可以看到,到这一步还是没有值的,即还没有bean实例存在IOC容器中。接着我们继续跑下一步
到这一步的时候可以看到 beanDefinitionMap 已经有bean存进去了,接下来我们重点看下
AnnotatedBeanDefinitionReader 构造方法 都做了哪些事情。
AnnotatedBeanDefinitionReader 构造方法
截图:
接着看其有参构造方法
截图:
代码:
/**
* Create a new {@code AnnotatedBeanDefinitionReader} for the given registry,
* using the given {@link Environment}.
* @param registry the {@code BeanFactory} to load bean definitions into,
* in the form of a {@code BeanDefinitionRegistry}
* @param environment the {@code Environment} to use when evaluating bean definition
* profiles.
* @since 3.1
*/
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);
}
接着看 registerAnnotationConfigProcessors 这个方法
继续看 registerAnnotationConfigProcessors 方法
截图:
代码:
/**
* Register all relevant annotation post processors in the given registry.
* @param registry the registry to operate on
* @param source the configuration source element (already extracted)
* that this registration was triggered from. May be {@code null}.
* @return a Set of BeanDefinitionHolders, containing all bean definitions
* that have actually been registered by this call
*/
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
//unwrap 打开...的包装,这里即获取默认bean工厂对象
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
//主要解析 @Order 和 @Priority beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
//提供处理延迟加载的功能
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
//spring 默认 BeanDefinition 的注册
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));
}
//注册 AutowiredAnnotationBeanPostProcessor
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));
}
//注册 CommonAnnotationBeanPostProcessor
// 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;
}
==> 这里其实就是6个默认的spring内部bean的注册
(1) ConfigurationClassPostProcessor 配置类后置处理器
工厂后置处理器,这个后置处理器非常重要,基本上类上面的注解都在这里面判断并解析,spring的包扫描也在里面完成
(2) AutowiredAnnotationBeanPostProcessor 自动导入注解Bean后处置理器
主要是@Autowired,是一个bean的后置处理器,在bean的属性注入的时候会用到
(3) CommonAnnotationBeanPostProcessor 通用注释Bean后置处理器
处理一些公共注解的,它是一个bean的后置处理器,可以处理@PostConstruct和@PreDestroy还有@Resource等
(4) PersistenceAnnotationBeanPostProcessor 持久性注释Bean后置处理器
对jpa
的处理,所以需要引入spring-orm的包,没有引入的话则spring不会注册这个类
(5) internalEventListenerProcessor 内部事件监听器处理器
对 @EventListener
注解的处理,spring实现事件监听的方式有很多种,其中一种就是在方法上添加 @EventListener
注解
(6) internalEventListenerFactory 内部事件监听器工厂
跟事件监听有关
接着我们看其中一个方法,挑第一个来跟一下逻辑代码
截图:
接着看 registerPostProcessor 这个方法
截图:
代码:
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//registry 就是 AnnotationApplicationContext
//这里是调用父类 GenericApplicationContext 中的 registerBeanDefinition 方法
//调用 beanFactory 将 spring 默认的 BeanDefinition 注册进去
registry.registerBeanDefinition(beanName, definition);
//一开始就初始化了 DefaultListableBeanFactory
return new BeanDefinitionHolder(definition, beanName);
}
接着看 registerBeanDefinition 方法
截图:
代码:
/**
* Register a new bean definition with this registry.//在此注册表中注册一个新的bean定义,
* Must support RootBeanDefinition and ChildBeanDefinition.//必须支持 RootBeanDefinition 和 ChildBeanDefinition
* @param beanName the name of the bean instance to register //beanName 要注册的bean实例的名称
* @param beanDefinition definition of the bean instance to register //beanDefinition 要注册的 bean 实例的定义
* @throws BeanDefinitionStoreException if the BeanDefinition is invalid
* @throws BeanDefinitionOverrideException if there is already a BeanDefinition
* for the specified bean name and we are not allowed to override it //指定bean的名称,我们不允许覆盖它
* @see GenericBeanDefinition
* @see RootBeanDefinition
* @see ChildBeanDefinition
*/
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;
这是一个接口,继续看其具体实现类
这里看默认的工厂实现类 DefaultListableBeanFactory
截图:
代码:
//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface
//---------------------------------------------------------------------
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
//在注册 bd 的时候判断该名字有没有被注册
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
//该名字已经被注册
//spring 默认支持覆盖 bd,但是 spring 会输入一些日志
//1、两个 bd 相同的情况下
//2、两个 bd 不同的情况 role 不同
//3、两个 bd 不相同但是 role 相同
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
//优先级
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
//判断我们的 spring 容器是否开启实例化 bean了
//如果为null,set 为空,没有开始就创建 bean 不会进入 if
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
//一个 map 一个 list ,list里面方法的 map 的 key,也就是 beanName
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
//如果注册了 beanDefinition 的名字和手工注册的 bd 集合当中某个相同则删除手动注册的 beanName
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
//判断注册的 bd 以及 beanName 是否存在
if (existingDefinition != null || containsSingleton(beanName)) {
//清除 allBeanNameByType
//把单例池当中的 bean 也 remove
resetBeanDefinition(beanName);
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
从这里可以看到bean已经存在到 IOC容器中,到此 AnnotatedBeanDefinitionReader 分析结束
接着看 ClassPathBeanDefinitionScanner 的构造方法
2.2 ClassPathBeanDefinitionScanner 构造方法
这个方法主要是创建BeanDefinition扫描器,可以用来扫描包或者类,继而转换为bd,spring默认的扫描器其实不是这个scanner对象, 而是在后面自己又重新new了一个ClassPathBeanDefinitionScanner, spring在执行工程后置处理器ConfigurationClassPostProcessor时,去扫描包时会new一个ClassPathBeanDefinitionScanner
这里的scanner仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法
所以这里不展开看了。
文章来源地址https://www.toymoban.com/news/detail-482090.html
文章来源:https://www.toymoban.com/news/detail-482090.html
3、最后回到我们最开始的地方, 可以看到 spring 初始化上下文已经有了,打个断点可以看到IOC容器已经实例化了一些对象,就是上面的6中默认bean,
截图:
参考博客:
1、https://blog.csdn.net/zzzzzyyyz/article/details/116999121
2、spring加载流程之AnnotatedBeanDefinitionReader_浴缸灬的博客-CSDN博客
3、SpringBoot源码深度剖析——@SpringBootApplication注解和new SpringApplication().run()方法深度解密_生活,没那么矫情的博客-CSDN博客
到了这里,关于SpringBoot 源码分析初始化应用上下文(1)-createApplicationContext的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!