springboot内嵌容器初始化
2022-01-12 17:39:48 8 举报
AI智能生成
springboot内嵌容器初始化
作者其他创作
大纲/内容
名称简写
SA
SpringApplication
springboot应用
SC
SpringContext
spring上下文(AnnotationConfigServletWebServerApplicationContext)
DF
DefaultListableBeanFactory
1. 实例化SpringApplication对象
1. 设置资源加载器,可以通过SA构造方法传入(SA缩写含义查看左侧说明)
this.resourceLoader = resourceLoader
this.resourceLoader = resourceLoader
2. 设置主配置源,即SpringBootApplicatio注解所在的类,这个类在#2.6.8中会被加载到DF#beanDefinitionMap中
在#2.7.5.1.2.1进行bean定义解析时会扫描该类同级及子包下的bean,还会解析该类注解中引入的其他bean定义
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
在#2.7.5.1.2.1进行bean定义解析时会扫描该类同级及子包下的bean,还会解析该类注解中引入的其他bean定义
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
3. 判断是否为web环境,设置到SA#webApplicationType 属性中
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.webApplicationType = WebApplicationType.deduceFromClasspath();
4. 获取应用上下文初始化器ApplicationContextInitializer,设置到SA#initializers中
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
顾名思义是用来对SC进行些初始化操作用的,在#2.6.3中会执行初始化方法
5. 获取应用监听器ApplicationListener,设置到SA#listeners中,和4中基本类似
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
此处会获取到一个比较关键的监听器:ConfigFileApplicationListener
该监听器会读取spring或第三方(如Apollo)yml或properties配置。详情查看#2.4.3
该监听器会读取spring或第三方(如Apollo)yml或properties配置。详情查看#2.4.3
2. 执行SpringApplication对象的run方法
1. 创建SpringApplicationRunListeners对象,主要是加载广播器,然后将#1.5中的应用监听放入到广播器中
SpringApplicationRunListeners listeners = getRunListeners(args);
2. 广播ApplicationStartingEvent事件
listeners.starting();
listeners.starting();
事件uml类关系图
自定义监听示例
3. 将main方法中的args转为ApplicationArguments对象,在#6.5中会被注册成单例bean
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
4. 构造容器环境
ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
1. 如果SA中environment为空,则创建StandardServletEnvironment对象(web环境)
ConfigurableEnvironment environment = getOrCreateEnvironment();
ConfigurableEnvironment environment = getOrCreateEnvironment();
1. 创建StandardServletEnvironment对象
1 执行AbstractEnvironment构造方法,回调子类的customizePropertySources方法
2. 执行StandardServletEnvironment的customizePropertySources方法
3. 执行StandardEnvironment的customizePropertySources方法
2. 对上一步构建的环境对象environment进行进一步配置
configureEnvironment(environment, applicationArguments.getSourceArgs());
configureEnvironment(environment, applicationArguments.getSourceArgs());
1. 通过双重检索的方式实例化一个单例ApplicationConversionService对象
2. 将单例对象设置到environment的propertyResolver属性的conversionService
2. 往environment中添加新的PropertySource
1. 往environment中添加defaultProperties
2. 往environment中添加commandLineArgs(添加到列表头,优先级最高)
3. 添加spring.profiles.active配置及additionalProfiles值到environment的activeProfiles
3. 广播ApplicationEnvironmentPreparedEvent事件
listeners.environmentPrepared(environment);
listeners.environmentPrepared(environment);
1. ConfigFileApplicationListener加载spring或第三方(如Apollo)yml或properties配置
1. 添加RandomValuePropertySource到environment
2. 实例化Loader对象
1. 设置属性值解析器placeholdersResolver
2. 设置资源加载器resourceLoader
3. 设置propertySourceLoaders(从spring.factories加载PropertySourceLoader配置)
3. 执行load方法
1. 执行initializeProfiles方法将active的配置添加到profiles队列
2. 循环处理profiles队列
1 如果当前profile不为null且不是default,添加到environment的activeProfiles列表中
2. 加载当前profile,将加载好的配置添加到loaded列表中
1. 获配置文件位置列表
2. 循环遍历位置列表
1. 对位置是目录的进行获取配置文件名列表(默认application)
2. 遍历上一步获取的文件列表加载配置添加到loaded
3. 将当前profile添加到已完成列表processedProfiles
4. 绑定environment对象到SpringApplication对象中
bindToSpringApplication(environment);
bindToSpringApplication(environment);
5. 添加configurationProperties到environment,如果已存在先移除再添加
ConfigurationPropertySources.attach(environment);
ConfigurationPropertySources.attach(environment);
5. 创建AnnotationConfigServletWebServerApplicationContext类型的应用上下文对象SC
context = createApplicationContext();
context = createApplicationContext();
1. 进入父类GenericApplicationContext执行构造方法实例化beanFactory属性为DF对象
2. 执行本类的无参构造
1. 实例化reader属性为AnnotatedBeanDefinitionReader对象
this.reader = new AnnotatedBeanDefinitionReader(this);
this.reader = new AnnotatedBeanDefinitionReader(this);
1. 设置registry 属性为SC
2. 设置conditionEvaluator属性为ConditionEvaluator对象,用来在doRegisterBean的时候判断需要注册的bean定义是否有@Conditional
(如:ConditionalOnBean,@Profile等注解都是包含该注解的)注解,有的话进一步判断条件是否满足,不满足则不进行注册操作
(如:ConditionalOnBean,@Profile等注解都是包含该注解的)注解,有的话进一步判断条件是否满足,不满足则不进行注册操作
3. 注册注解配置的后置处理器
1. 设置DF#dependencyComparator为AnnotationAwareOrderComparator
能解析 @Order 注解和 @Priority 注解
2. 设置DF#autowireCandidateResolver为ContextAnnotationAutowireCandidateResolver
提供处理延迟加载的功能
3. 将beanFactory后置处理器ConfigurationClassPostProcessor注册到DF#beanDefinitionMap中
该后置处理器非常的重要,主要用来解析bean定义,在#2.7.5.1.2中会被实例化
该后置处理器非常的重要,主要用来解析bean定义,在#2.7.5.1.2中会被实例化
4. 将bean后置处理器AutowiredAnnotationBeanPostProcessor注册到DF#beanDefinitionMap中
也是比较重要的一个,主要用来处理bean依赖注入,如@Autowired依赖注入
也是比较重要的一个,主要用来处理bean依赖注入,如@Autowired依赖注入
5. 将bean后置处理器CommonAnnotationBeanPostProcessor注册到DF#beanDefinitionMap中
和AutowiredAnnotationBeanPostProcessor类似,主要要来处理java中自带的注解,如@Resource
和AutowiredAnnotationBeanPostProcessor类似,主要要来处理java中自带的注解,如@Resource
6. 将beanFactory后置处理器EventListenerMethodProcessor注册到DF#beanDefinitionMap中
在#2.7.11.5.2中会被使用到,用来在所有非lazy单例Bean实例化完成后做些事情,如:将@EventListener注册的监听添加到SC事件发布器中
在#2.7.11.5.2中会被使用到,用来在所有非lazy单例Bean实例化完成后做些事情,如:将@EventListener注册的监听添加到SC事件发布器中
7. 将DefaultEventListenerFactory注册到DF#beanDefinitionMap中
2. 实例化scanner属性为ClassPathBeanDefinitionScanner对象
this.scanner = new ClassPathBeanDefinitionScanner(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
1. 设置registry 属性为SC
2. 注册默认的过滤器,比如注解过滤器用来表示标注了该注解的类才进行扫描
也可以通过new AnnotationTypeFilter(Component.class)的方式定义过滤器添加进来
也可以通过new AnnotationTypeFilter(Component.class)的方式定义过滤器添加进来
3. 设置environment
4. 设置resourceLoader
1. 设置resourcePatternResolver
2. 设置metadataReaderFactory
6. 对上一步创建的SC进行些设置,为下一步进行refresh 做些准备工作
prepareContext(context, environment, listeners, applicationArguments,printedBanner);
prepareContext(context, environment, listeners, applicationArguments,printedBanner);
1. 设置环境为#2.4中构建的环境对象,主要包括三个地方
context.setEnvironment(environment);
context.setEnvironment(environment);
1. 设置父类AbstractApplicationContext的environment属性
2. 通过environment构造ConditionEvaluator设置到reader的
3. 设置scanner的environment属性
2. 设置beanFactory的conversionService属性为ApplicationConversionService
postProcessApplicationContext(context)
postProcessApplicationContext(context)
3. 循环调用#1.4中initializers对象的initialize(C applicationContext)方法,执行一些初始化操作
applyInitializers(context);
applyInitializers(context);
1. 其中有两个对象的initialize方法会执行addBeanFactoryPostProcessor方法
往SC#beanFactoryPostProcessors中添加beanFactory后置处理器,在#2.7.5.1中将会执行
往SC#beanFactoryPostProcessors中添加beanFactory后置处理器,在#2.7.5.1中将会执行
SharedMetadataReaderFactoryContextInitializer
添加CachingMetadataReaderFactoryPostProcessor
添加CachingMetadataReaderFactoryPostProcessor
ConfigurationWarningsApplicationContextInitializer
添加ConfigurationWarningsPostProcessor
添加ConfigurationWarningsPostProcessor
4. 广播ApplicationContextInitializedEvent事件
listeners.contextPrepared(context);
listeners.contextPrepared(context);
5. 通过#2.3中的ApplicationArguments对象注册成单例bean springApplicationArguments
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
6. 如果beanFactory为DefaultListableBeanFactory则设置allowBeanDefinitionOverriding值为false,表示不允许用相同的名称重新注册
setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding)
setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding)
需要注意的是通过ClassPathBeanDefinitionScanner扫描的方式注册bean时如果出现bean名称相同该值是不起作用的
因为在调用DF中的注册方法之前就会对扫描到的包进行检查,详情查看#2.6.8.2.2.1.2.2.5
因为在调用DF中的注册方法之前就会对扫描到的包进行检查,详情查看#2.6.8.2.2.1.2.2.5
7. 获取#1.2中的primarySources及SA中的sources(可通过SpringApplication#setSources方法设置)添加到Set中
Set<Object> sources = getAllSources();
Set<Object> sources = getAllSources();
8. 将#2.6.7中获取的sources加载到SC中
load(context, sources.toArray(new Object[0]));
load(context, sources.toArray(new Object[0]));
1. 通过#2.6.7中获取的source和SC中的beanFactory创建一个BeanDefinitionLoader对象
BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
1. 设置需要加载的sources为#2.6.7中获取的sources
2. 实例化一个新的AnnotatedBeanDefinitionReader对象annotatedReader用来加载注解类型的BeanDefinition
primarySources会被该对象注册到DF#beanDefinitionMap中
primarySources会被该对象注册到DF#beanDefinitionMap中
3. 实例化一个XmlBeanDefinitionReader对象用来加载xml类型的BeanDefinition
4. 实例化一个ClassPathBeanDefinitionScanner对象scanner用来以包扫描的方式注册BeanDefinition
5. 为4中的scanner对象设置不过滤规则,将sources中Class类型的source放入到过滤列表中
2. 调用loader.load()方法将source逐一加载
1. 通过#2.6.8.1.2创建的annotatedReader对象注册primarySources
1. 判断该类是否符合加载条件,比如有Component注解则直接进行加载
2. 通过annotatedReader.register方法进行注册
最终注册逻辑在doRegisterBean方法中完成
最终注册逻辑在doRegisterBean方法中完成
1. 通过注解类annotatedClass构造一个AnnotatedGenericBeanDefinition对象 abd
2. 通过 conditionEvaluator.shouldSkip方法判断abd元数据中是否有Conditional注解且满足加载条件
不满足则直接不进行接下来的注册操作,关于conditionEvaluator在#2.5.2.1.2中有描述
不满足则直接不进行接下来的注册操作,关于conditionEvaluator在#2.5.2.1.2中有描述
3. 指定创建 bean 实例的回调方法,此处为 null
4. 解析adb中是否有指定scope(没指定默认为单例),设置到abd中
5. 通过beanNameGenerator获取bean名称beanName
6. 主要处理 @Lazy @DependsOn @Primary @Role @Description 等注解,处理完成后设置到abd中
7. 主要是用来处理注册时有传qualifiers的情况
8. 将 ./5中获取的beanName和adb构造成一个BeanDefinitionHolder对象definitionHolder
9. 设置代理模型,此处不进行代理,直接返回definitionHolder
10. 通过工具类BeanDefinitionReaderUtils.registerBeanDefinition方法进行注册操作
1. 从definitionHolder中取出beanName
2. 调用SC对象的registerBeanDefinition方法进行注册,实际上是调用DF#registerBeanDefinition方法
将bean定义注册到DF#beanDefinitionMap中
将bean定义注册到DF#beanDefinitionMap中
3. 如果有设置别名则进行别名注册
2. 通过#2.6.8.1.4中的scanner扫描包路径注册
(需要设置SC属性sources且source为包路径才会执行此操作)
(需要设置SC属性sources且source为包路径才会执行此操作)
1. 执行scanner.scan方法进行注册
1. 获取已经注册的BeanDefinition总数量beanCountAtScanStart
2. 执行真正的扫描注册逻辑
1. 调用父类ClassPathScanningCandidateComponentProvider#findCandidateComponents方法
查找包路径下符合条件的class转化成ScannedGenericBeanDefinition添加到集合candidates中
此处不会去管class中是否又引入其他class 配置,那是#2.7.5.1.2中ConfigurationClassPostProcessor 干的事
查找包路径下符合条件的class转化成ScannedGenericBeanDefinition添加到集合candidates中
此处不会去管class中是否又引入其他class 配置,那是#2.7.5.1.2中ConfigurationClassPostProcessor 干的事
1. class文件是否可读的
2. class文件不在excludeFilters过滤规则且在includeFilters(如有@Component注解)规则
3. 该class是可实例化的
2. 循环BeanDefinition集合candidates
1. 解析scope属性并设置到candidate
2. 通过beanNameGenerator获取bean名称beanName
3. 如果candidate是AbstractBeanDefinition类型,则为candidate设置默认值(如是否懒加载,初始化方法,销毁方法等)
4. 如果candidate是AnnotatedBeanDefinition类型,则判断是否有Primary,DependsOn,Lazy等注解,有则设置对应的值到candidate
5. 对将要添加的bean名称做检查
如果该bean名称没有被注册过则和#2.6.8.2.1.2.10中那样通过
BeanDefinitionReaderUtils.registerBeanDefinition方法进行注册
BeanDefinitionReaderUtils.registerBeanDefinition方法进行注册
如果bean名称被注册过了则判断将要添加的bean定义和已经存在的bean定义是否兼容
兼容则不进行注册,不兼容则抛出ConflictingBeanDefinitionException异常
兼容则不进行注册,不兼容则抛出ConflictingBeanDefinitionException异常
满足其中一个条件则表示兼容
1. 已经存在的bean定义不是ScannedGenericBeanDefinition实例
2. 新注册的bean定义和已经存在的bean定义source相同(说明是同一个.class被扫描了两次)
3. 新注册的bean定义和已经存在的bean定义本身是相同的
3. 计算注册的BeanDefinition数量进行返回
9. 广播ApplicationPreparedEvent事件
listeners.contextLoaded(context);
listeners.contextLoaded(context);
1. 会循环SA中所有的监听器添加到SC中,如果监听器实现了ApplicationContextAware接口,会先执行监听器的setApplicationContext方法
2. 通过广播器内部的initialMulticaster对象广播ApplicationPreparedEvent事件
1. 其中ConfigFileApplicationListener监听器会监听该事件
并往SC#beanFactoryPostProcessors中添加beanFactory后置处理器,在#2.7.5.1中将会执行
并往SC#beanFactoryPostProcessors中添加beanFactory后置处理器,在#2.7.5.1中将会执行
7. refresh应用上下文
refreshContext(context);
refreshContext(context);
1. 为应用上下文刷新做些准备工作
prepareRefresh();
prepareRefresh();
1 清除SC中scanner对象的metadataReaderFactory属性的本地类元数据缓存
2. 调用父类的prepareRefresh方法
1. 设置应用上下文启动时间
2. 设置应用上下文close状态为false
3. 设置应用上下文active状态为true
4. 对environment做些初始化操作,比如上下文中有设置servletContext值则会从设置的对象中取出
servletContextInitParams替换environment中设置的servletContextInitParams
servletContextInitParams替换environment中设置的servletContextInitParams
5. 验证environment必填属性是否填写
6. 设置监听器为#1.5中的那些监听器到SC中
2. 获取beanFactory对象,该对象在#2.5.1中已经创建好了
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
1. 调用DF#setSerializationId方法往serializableFactories Map属性中put值
key为spring应用的名称,值为一个弱引用,该弱引用引用对象为当前DF对象
key为spring应用的名称,值为一个弱引用,该弱引用引用对象为当前DF对象
2. 将DF对象#2.5.1中的DF对象返回
3. 对beanFactory做些准备工作
prepareBeanFactory(beanFactory)
prepareBeanFactory(beanFactory)
1. 设置DF的beanClassLoader为SC的classLoader
2. 设置EL表达式解析器(Bean初始化完成后填充属性时会用到)
3. 设置属性注册解析器PropertyEditor 这个主要是对bean的属性等设置管理的一个工具
4. 添加ApplicationContextAwareProcessor bean后置处理器,用于实现在bean中对SC的织入
需要注意的是该处理器postProcessBeforeInitialization方法除了会判断是否实现了ApplicationContextAware接口进行织入外
还会判断是否有实现右侧的接口,因为SC实现了右侧的那个些接口,直接将SC转为对应的接口类型即可。
因此会将右侧的那些接口添加到ignoreDependencyInterface中,被添加到ignoreDependencyInterface中的接口被
bean实现setXXX方法则就不会进行依赖注入了(如通过@AutoWrite注解依赖)
需要注意的是该处理器postProcessBeforeInitialization方法除了会判断是否实现了ApplicationContextAware接口进行织入外
还会判断是否有实现右侧的接口,因为SC实现了右侧的那个些接口,直接将SC转为对应的接口类型即可。
因此会将右侧的那些接口添加到ignoreDependencyInterface中,被添加到ignoreDependencyInterface中的接口被
bean实现setXXX方法则就不会进行依赖注入了(如通过@AutoWrite注解依赖)
EnvironmentAware
EmbeddedValueResolverAware
ResourceLoaderAware
ApplicationEventPublisherAware
MessageSourceAware
ApplicationContextAware
5. 往resolvableDependencies中添加自动装配对象,这些自动装配的对象不会以bean的形式存在IOC容器中
但却可以通过@Autowired装配,因为在依赖注入时会先检查resolvableDependencies中是否存在依赖的bean
但却可以通过@Autowired装配,因为在依赖注入时会先检查resolvableDependencies中是否存在依赖的bean
BeanFactory
ResourceLoader
ApplicationEventPublisher
ApplicationContext
6. 添加ApplicationListenerDetector bean后置处理器,用于在Bean初始化后检查是否实现了ApplicationListener接口,实现了就添加到applicationListeners中
7. 检查容器中是否包含名称为loadTimeWeaver的bean,有则添加LoadTimeWeaverAwareProcessor bean后置处理器
实际上是增加Aspectj的支持
实际上是增加Aspectj的支持
8. 注入单例bean environment
9. 注入单例bean systemProperties
10. 注入单例bean systemEnvironment
4. AbstractApplicationContext模板方法,供子类做些自定义实现
postProcessBeanFactory(beanFactory);
postProcessBeanFactory(beanFactory);
1. 调用SC父类ServletWebServerApplicationContext的postProcessBeanFactory方法
1. 添加WebApplicationContextServletContextAwareProcessor bean后置处理器
为实现ServletContextAware接口的bean设置ServletContext对象
或为实现ServletConfigAware接口的bean设置ServletConfig对象
为实现ServletContextAware接口的bean设置ServletContext对象
或为实现ServletConfigAware接口的bean设置ServletConfig对象
2. 将ServletContextAware类型添加到ignoredDependencyInterfaces中
因为后置处理器WebApplicationContextServletContextAwareProcessor的父处理器中会对该接口进行了处理
关于ignoredDependencyInterfaces查看#2.7.3.4
因为后置处理器WebApplicationContextServletContextAwareProcessor的父处理器中会对该接口进行了处理
关于ignoredDependencyInterfaces查看#2.7.3.4
3. 注册scrop及resolvableDependencies
1. 实例化一个RequestScope对象添加到DF#scopes中,key为request
在doGetBean源码分析#4.9.2中会使用
2. 实例化一个SessionScope对象添加到DF#scopes中,key为session
在doGetBean源码分析#4.9.2中会使用
3. 实例化一个RequestObjectFactory对象添加到resolvableDependencies中,key为ServletRequest.class
此处是@AutoWrite HttpServletRequest时保证线程安全的关键
在依赖注入HttpServletRequest时其实是注入了AutowireUtils#ObjectFactoryDelegatingInvocationHandler代理对象(代码见备注)
该代理对象代理了HttpServletRequest的所有方法,在调用某个方法时先通过RequestObjectFactory#getObject获取当前请求的request对象
然后通过request对象反射执行对应的方法,从而保证线程安全性
在依赖注入HttpServletRequest时其实是注入了AutowireUtils#ObjectFactoryDelegatingInvocationHandler代理对象(代码见备注)
该代理对象代理了HttpServletRequest的所有方法,在调用某个方法时先通过RequestObjectFactory#getObject获取当前请求的request对象
然后通过request对象反射执行对应的方法,从而保证线程安全性
4. 实例化一个ResponseObjectFactory对象添加到resolvableDependencies中,key为ServletResponse.class
5. 实例化一个SessionObjectFactory对象添加到resolvableDependencies中,key为HttpSession.class
6. 实例化一个WebRequestObjectFactory对象添加到resolvableDependencies中,key为WebRequest.class
2. SA#basePackages属性是否有值,有值则进行scanner.scan操作将符合条件的bean定义先注册beanDefinitionMap中
3. 和上面操作相似,只是是通过注解的方式进行加载
5. 执行BeanFactory后置处理器
invokeBeanFactoryPostProcessors(beanFactory)
invokeBeanFactoryPostProcessors(beanFactory)
1. 将DF和SC#beanFactoryPostProcessors做为参数调用
PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors方法
PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors方法
1. 循环SC#beanFactoryPostProcessors中的后置处理器,如果处理器实现了
BeanDefinitionRegistryPostProcessor则执先行该处理器的postProcessBeanDefinitionRegistry方法
然后添加处理器到registryProcessors 列表中,否则添加到regularPostProcessors列表中
BeanDefinitionRegistryPostProcessor则执先行该处理器的postProcessBeanDefinitionRegistry方法
然后添加处理器到registryProcessors 列表中,否则添加到regularPostProcessors列表中
2. 从DF(包含beanDefinitionMap和已手动注册的单例bean)中获取所有实现了BeanDefinitionRegistryPostProcessor的
beanDefinition,再从中筛选出实现了PriorityOrdered接口的处理器进行加载成bean实例后执行
postProcessBeanDefinitionRegistry方法,最后将该处理器实例添加到registryProcessors 列表中
(其实此处符合执行条件的就只有#2.5.2.1.3.3中添加的ConfigurationClassPostProcessor)
beanDefinition,再从中筛选出实现了PriorityOrdered接口的处理器进行加载成bean实例后执行
postProcessBeanDefinitionRegistry方法,最后将该处理器实例添加到registryProcessors 列表中
(其实此处符合执行条件的就只有#2.5.2.1.3.3中添加的ConfigurationClassPostProcessor)
1. ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
会在此时执行(在#2.5.2.1.3.3中被添加进来了),该处理器实现了PriorityOrdered接口
所以优先级会比较高
会在此时执行(在#2.5.2.1.3.3中被添加进来了),该处理器实现了PriorityOrdered接口
所以优先级会比较高
1. 根据beandefinitionregistry生成全局唯一的registryid
2. 如果该registeryid已经执行过了则抛出异常,不再执行
3. 将当前registeryid添加到registriespostprocessed中
用于后面进来判断是否已执行
用于后面进来判断是否已执行
4. 执行真正的解析逻辑
1. 从df#beanDefinitionmap中找出符合条件的beanDef放入configcandidates列表中
所谓的符合条件的有两种情况包含右侧两种情况,两者的区别见备注
此时@SpringBootApplication标识的类会被添加(在#2.6.8.2.1放入beanDefinitionMap)
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
所谓的符合条件的有两种情况包含右侧两种情况,两者的区别见备注
此时@SpringBootApplication标识的类会被添加(在#2.6.8.2.1放入beanDefinitionMap)
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
1. "Full"模式
有@Configuration注解的类,是则标识为full属性值
有@Configuration注解的类,是则标识为full属性值
2. "lite"模式
有@Component,@ComponentScan,@Import,@ImportResource注解的类
或在@Component注解类中通过@Bean注解标识方法的方式
有@Component,@ComponentScan,@Import,@ImportResource注解的类
或在@Component注解类中通过@Bean注解标识方法的方式
2. 对 configCandidates 进行按优先级排序
3. 为Bean扫描方式及import方式设置BeanNameGenerator
如果DF中没有internalConfigurationBeanNameGenerator单例bean
则使用默认的AnnotationBeanNameGenerator
其生成规则为Bean扫描方式为首字母小写,import模式为全类名
则使用默认的AnnotationBeanNameGenerator
其生成规则为Bean扫描方式为首字母小写,import模式为全类名
4. 设置environment,此处environment不为空不会执行,因为ConfigurationClassPostProcessor
实现了EnvironmentAware接口在bean初始化的时候就被织入了environment
实现了EnvironmentAware接口在bean初始化的时候就被织入了environment
5. 实例化ConfigurationClassParser对象parser
6. 将List 对象configCandidates构建成一个Set 对象candidates进行去重处理
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
7. 循环解析candidates 中bean定义引入的相关ConfigurationClass对象
然后将这些对象解析为bean定义添加到DF#beanDefinitionmap中
然后将这些对象解析为bean定义添加到DF#beanDefinitionmap中
1. 执行parse操作
parser.parse(candidates);
parser.parse(candidates);
1. 针对不同的BeanDefinition构造成ConfigurationClass对象
然后调用 processConfigurationClass(ConfigurationClass configClass)
然后调用 processConfigurationClass(ConfigurationClass configClass)
1. 判断是否加载这个配置类,如果不满足Condition注解条件则直接返回
2. 如果这个配置类已经存在configurationClasses中了
1.如果当前需要继续的configClass是@Import类型的
1. 存在的那个configClass也是@Import则进行合并操作
2. 不符合上面的条件则不进行当前configClasss的解析操作了
2. 如果上一步的条件则移除已存在的,继续解析当前configClass
3. 将configClass 作为原始类,在下一步的解析操作中如果原始类的父类符合解析条件会递归解析
SourceClass sourceClass = asSourceClass(configClass);
SourceClass sourceClass = asSourceClass(configClass);
4. 执行configClass解析操作,会通过 do{}while(sourceClass!=null) 递归解析父类
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
1. 先处理内部类中是否有内部类配置,有则先处理内部类配置
2. 对@PropertySource注解进行解析,如@PropertySource("classpath:test.properties")
会将该配置添加到environment中
会将该配置添加到environment中
3. 处理@ComponentScans
先获取所有的@ComponentScans,然后循环执行扫描操作(通过ComponentScanAnnotationParser)
扫描到bean会直接被添加到DF#beanDefinitionmap中,不会等到 ../../../3 中loadBeanDefinitions再添加
而且如果被添加的bean定义是full或lite bean 则递归执行 ../../../1 的parse操作
先获取所有的@ComponentScans,然后循环执行扫描操作(通过ComponentScanAnnotationParser)
扫描到bean会直接被添加到DF#beanDefinitionmap中,不会等到 ../../../3 中loadBeanDefinitions再添加
而且如果被添加的bean定义是full或lite bean 则递归执行 ../../../1 的parse操作
4. 处理@Import注解
1. 将@Import注解中的Class值包装为SourceClass放入Set<SourceClass> imports中
供下一步processImports使用,此过程会递归查找包装后的SourceClass中是否又有@Import
其他Class,有的话也会添加到improts集合中
getImports(sourceClass)
供下一步processImports使用,此过程会递归查找包装后的SourceClass中是否又有@Import
其他Class,有的话也会添加到improts集合中
getImports(sourceClass)
2. 循环解析上一步获取的imports,最后的true参数表示检测循环import
processImports(configClass, sourceClass, imports, true);
processImports(configClass, sourceClass, imports, true);
1. 如果importCandidates(实参为imports)为空直接return
2. 如果存在循环@import则抛出CircularImportProblem异常
3. 循环importCandidates
1. 如果当前candidate实现了ImportSelector接口,否则进入下一步逻辑
1. 实例化当前candidate的类并转为ImportSelector类型对象selector
2. 对上一步的selector进行一些Aware
3. 判断该selector是否还实现了DeferredImportSelector接口
有则添加到deferredImportSelectorHandler中,在../../../../../../2中解析
否则进入下一步逻辑
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
有则添加到deferredImportSelectorHandler中,在../../../../../../2中解析
否则进入下一步逻辑
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
4. selector没有实现DeferredImportSelector接口,通过selector.selectImports
查找出需要import的类名称数组,再将该数组包装为Collection<SourceClass>集合importSourceClasses
最后递归调用 ../../2 的processImports方法将selectImports进来的那些类进行解析
processImports(configClass, currentSourceClass, importSourceClasses, false);
查找出需要import的类名称数组,再将该数组包装为Collection<SourceClass>集合importSourceClasses
最后递归调用 ../../2 的processImports方法将selectImports进来的那些类进行解析
processImports(configClass, currentSourceClass, importSourceClasses, false);
2. 如果当前candidate实现了ImportBeanDefinitionRegistrar接口,否则进入下一步逻辑
1. 实例化当前candidate的类并转为ImportBeanDefinitionRegistrar类型对象registrar
2. 对上一步的registrar进行一些Aware
3. 将registrar 添加到configClass#importBeanDefinitionRegistrars中
key为registrar,值为currentSourceClass.getMetadata()
key为registrar,值为currentSourceClass.getMetadata()
3. 将当前currentSourceClass的元数据信息添加到ConfigurationClassParser,内部类ImportStack的import属性中
key为当前candidate的类名称,值为currentSourceClass.getMetadata()(在实现ImportAware接口时setImportMetadata方法中的参数值就是来源于此处)
然后递归调用 ../../../../../1 的processConfigurationClass方法解析当前candidate
需要注意的是asConfigClass时传入了configClass,这样configClass将会被添加到构建的ConfigurationClass#importedBy集合中
processConfigurationClass(candidate.asConfigClass(configClass));
key为当前candidate的类名称,值为currentSourceClass.getMetadata()(在实现ImportAware接口时setImportMetadata方法中的参数值就是来源于此处)
然后递归调用 ../../../../../1 的processConfigurationClass方法解析当前candidate
需要注意的是asConfigClass时传入了configClass,这样configClass将会被添加到构建的ConfigurationClass#importedBy集合中
processConfigurationClass(candidate.asConfigClass(configClass));
ImportAware使用示例
5. 处理@ImportResource注解
获取@ImportResource注解中locations属性的数组值String[] resources
再取出reader属性的值Class readerClass(默认值为BeanDefinitionReader.class)
最后循环resources 添加到当前configClass#importedResources中可以为 resource,值为readerClass
在添加前会将resource中的占位符通过环境变量中的值进行替换
获取@ImportResource注解中locations属性的数组值String[] resources
再取出reader属性的值Class readerClass(默认值为BeanDefinitionReader.class)
最后循环resources 添加到当前configClass#importedResources中可以为 resource,值为readerClass
在添加前会将resource中的占位符通过环境变量中的值进行替换
6. 处理@Bean注解的方法
获取所有@Bean注解值放入Set<MethodMetadata> beanMethods集合中
然后循环beanMethods将MethodMetadata 包装成BeanMethod对象后添加到
当前configClass#beanMethods属性中
获取所有@Bean注解值放入Set<MethodMetadata> beanMethods集合中
然后循环beanMethods将MethodMetadata 包装成BeanMethod对象后添加到
当前configClass#beanMethods属性中
7. 处理接口上带@Bean的默认方法
和上一步一样,只不过是去当前configClass类的实现接口中查找默认方法上是否有@Bean注解
和上一步一样,只不过是去当前configClass类的实现接口中查找默认方法上是否有@Bean注解
8. 如果当前sourceClass有父类且父类名称非java开头,则返回父类的sourceClass包装递归解析父类
否则的话返回null跳出 ../4 中的do while循环
否则的话返回null跳出 ../4 中的do while循环
5. 将解析好的当前configClass添加到ConfigurationClassParser#configurationClassess
属性中,key和value都是当前configClass
this.configurationClasses.put(configClass, configClass);
属性中,key和value都是当前configClass
this.configurationClasses.put(configClass, configClass);
2. 处理上一步处理过程中需要延迟执行的ImportSelector(./1.4.4.2.3.1.3出添加)
this.deferredImportSelectorHandler.process();
this.deferredImportSelectorHandler.process();
2. 对解析出来的对象做校验,主要是对有解析出来的带@Configuration注解的对象进行校验
主要是为了支持#2.7.1.5.1中对full模式的bean进行cglib代理
parser.validate();
主要是为了支持#2.7.1.5.1中对full模式的bean进行cglib代理
parser.validate();
标注@Configuration的类不能被Final修饰
不然会抛出FinalConfigurationProblem异常
不然会抛出FinalConfigurationProblem异常
标注@Configuration的类中有@Bean注解标注的方法则该方法需要能被冲洗
不然会抛出NonOverridableMethodError异常
不然会抛出NonOverridableMethodError异常
3. 通过ConfigurationClassBeanDefinitionReader对象将上一步解析出来的
ConfigurationClass对象列表做为bean定义循环添加到DF#beanDefinitionmap中
this.reader.loadBeanDefinitions(configClasses);
ConfigurationClass对象列表做为bean定义循环添加到DF#beanDefinitionmap中
this.reader.loadBeanDefinitions(configClasses);
1. 判断是否要跳过该configClass加载,有如右两种情况需要跳过
1. 该configClass的类是@Import value属性中导入的类(通过importedBy属性不为空表示是@Import导入)
且引入该@Import注解的类本身也是被@Import导入的。
importedBy属性的设置可以查看 ../../1.1.4.4.2.3.3
且引入该@Import注解的类本身也是被@Import导入的。
importedBy属性的设置可以查看 ../../1.1.4.4.2.3.3
2. 标注了@Condition注解且不满足条件
2. 对@Import导入的configClass注册为bean定义,能来到此处说明importedBy属性为空
不然上一步就被跳过了
registerBeanDefinitionForImportedConfigurationClass(configClass);
不然上一步就被跳过了
registerBeanDefinitionForImportedConfigurationClass(configClass);
3. 对包含@Bean标注方法的configClass进行处理,循环将所有的方法注册为bean定义
loadBeanDefinitionsForBeanMethod(beanMethod);
loadBeanDefinitionsForBeanMethod(beanMethod);
需要注意的是:同一个配置类中通过@Bean("xxx")定义两个相同名称的bean会忽略后面定义的那个
如果是不同的配置类中通过@Bean定义两个相同名称的bean在执行注册的时候会判断allowBeanDefinitionOverriding的值
如果该值为false则会抛出BeanDefinitionOverrideException异常
如果是不同的配置类中通过@Bean定义两个相同名称的bean在执行注册的时候会判断allowBeanDefinitionOverriding的值
如果该值为false则会抛出BeanDefinitionOverrideException异常
4. 对ImportedResources 的configClass进行注册
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
5. 对@Import导入且实现了ImportBeanDefinitionRegistrar接口(../../1.1.4.4.2.3.3)的configClass注册为bean定义
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
4. 如果DF中通过上一步新增的bean定义中存在未解析的full或lite bean定义
则继续添加到 candidates中继续解析
则继续添加到 candidates中继续解析
8. 将ConfigurationClassParser对象中的importStack属性注册为单例bean
通过上面的操作importStack中保存了所以@Import进来的配置类信息,比如在实现ImportAware接口时会用到
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
通过上面的操作importStack中保存了所以@Import进来的配置类信息,比如在实现ImportAware接口时会用到
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
ImportAware使用示例
3. 和2中一样,只不过是筛选出只实现了Ordered(该接口是PriorityOrdered的父接口)接口的处理器
其实目的只是为了控制那些实现了PriorityOrdered接口的处理器能先执行
其实目的只是为了控制那些实现了PriorityOrdered接口的处理器能先执行
像自定义类只实现BeanDefinitionRegistryPostProcessor接口的话会在这一步执行
postProcessBeanDefinitionRegistry方法
postProcessBeanDefinitionRegistry方法
4. 和2中一样,只不过是将那些既没有实现PriorityOrdered接口,也没实现Ordered接口的处理器进行执行
postProcessBeanDefinitionRegistry方法,同样是为了控制处理器的执行顺序
postProcessBeanDefinitionRegistry方法,同样是为了控制处理器的执行顺序
5. 循环执行registryProcessors中beanFactory处理器的postProcessBeanFactory方法
1. ConfigurationClassPostProcessor#postProcessBeanFactory
方法会在此时执行
方法会在此时执行
1. 对@Configuration注解的beanDefinition进行cglib代理增强
enhanceConfigurationClasses(beanFactory);
enhanceConfigurationClasses(beanFactory);
2. 添加 ImportAwareBeanPostProcessor后置处理器
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
6. 循环执行regularPostProcessors中beanFactory处理器的postProcessBeanFactory方法
7. 和2中类似,只不过是从DF中获取所有实现了BeanFactoryPostProcessor
的后置处理器,执行顺序也是和BeanDefinitionRegistryPostProcessor一样
按照PriorityOrdered,Ordered,nonOrdered的顺序执行处理器的postProcessBeanFactory方法
的后置处理器,执行顺序也是和BeanDefinitionRegistryPostProcessor一样
按照PriorityOrdered,Ordered,nonOrdered的顺序执行处理器的postProcessBeanFactory方法
PropertySourcesPlaceholderConfigurer#postProcessBeanFactory将在这一步被调用
该后置处理器是由PropertyPlaceholderAutoConfiguration自动引入进来的
会通过环境中的值替换${}占位符中的值,需要注意的是@Value注解中的${}占位符是在属性依赖的时候进行解析的
该后置处理器是由PropertyPlaceholderAutoConfiguration自动引入进来的
会通过环境中的值替换${}占位符中的值,需要注意的是@Value注解中的${}占位符是在属性依赖的时候进行解析的
2. 和#2.7.3.7做同样的事情
6. 按优先顺序将BeanPostProcessor类型的bean定义取出实例化后添加到DF#beanPostProcessors中
registerBeanPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
1.获取DF中类型为BeanPostProcessor的所有bean名称postProcessorNames,会从beanDefinitionNames和manualSingletonNames中去查找
2. 添加BeanPostProcessorChecker bean后置处理器到DF#beanPostProcessors中
3. 主要逻辑为按priorityOrdered,ordered,nonOrdered的顺序分别将1中postProcessorNames包含的bean取出各自排序后添加到DF#beanPostProcessors中
在各自取出的过程中如果bean实现了MergedBeanDefinitionPostProcessor则放在一个list中等其他beanPostProcessor都添加好了再添加
整个过程和#2.7.5.1有点类似,只是没有执行后置处理器中的方法,只是添加到了DF#beanPostProcessors中
需要注意的是自定义的bean如果实现了BeanPostProcessor接口在这一步就加载bean了,而不是在 #2.7.11进行加载,所以想要对实现了BeanPostProcessor接口的
bean初始化的时候执行postProcessAfterInitialization或postProcessBeforeInitialization则需要定义一个优先级比它高的处理器
在各自取出的过程中如果bean实现了MergedBeanDefinitionPostProcessor则放在一个list中等其他beanPostProcessor都添加好了再添加
整个过程和#2.7.5.1有点类似,只是没有执行后置处理器中的方法,只是添加到了DF#beanPostProcessors中
需要注意的是自定义的bean如果实现了BeanPostProcessor接口在这一步就加载bean了,而不是在 #2.7.11进行加载,所以想要对实现了BeanPostProcessor接口的
bean初始化的时候执行postProcessAfterInitialization或postProcessBeforeInitialization则需要定义一个优先级比它高的处理器
4. 添加ApplicationListenerDetector bean后置处理器到DF#beanPostProcessors中
其实在#2.7.3.6中已经添加了该处理器,这里再次添加只是为了让该处理器处于列表的最后,因为添加DF#addBeanPostProcessor方法会先移除再添加
其实在#2.7.3.6中已经添加了该处理器,这里再次添加只是为了让该处理器处于列表的最后,因为添加DF#addBeanPostProcessor方法会先移除再添加
7. 初始化消息源
initMessageSource();
initMessageSource();
1. 实例化一个DelegatingMessageSource对象dms
2. 为dms设置父MessageSource
3. 将dms注册为一个名为messageSource的单例bean
8. 初始化SC的事件多播器applicationEventMulticaster为SimpleApplicationEventMulticaster,并注册为单例bean
initApplicationEventMulticaster();
initApplicationEventMulticaster();
9. 创建web服务
onRefresh();
onRefresh();
1. 调用父类GenericWebApplicationContext#onRefresh方法初始化模板源
2. 调用createWebServer()方法,执行创建web服务的操作
1. 从DF中加载ServletWebServerFactory类型的bean,springboot默认内嵌tomcat
所以此处加载的是TomcatServletWebServerFactory
所以此处加载的是TomcatServletWebServerFactory
在autoconfigure模块的spring.factories文件中有引入ServletWebServerFactoryAutoConfiguration
ServletWebServerFactoryAutoConfiguration类中Import了多个静态类,包括EmbeddedTomcat.class,EmbeddedJetty.class
其中EmbeddedTomcat.class会通过@Bean引入TomcatServletWebServerFactory bean
ServletWebServerFactoryAutoConfiguration类中Import了多个静态类,包括EmbeddedTomcat.class,EmbeddedJetty.class
其中EmbeddedTomcat.class会通过@Bean引入TomcatServletWebServerFactory bean
2. 执行ServletWebServerFactory#getWebServer方法,该方法接收一个ServletContextInitializer 对象
在getWebServer方法中会实例化一个TomcatWebServer对象进行返回,在TomcatWebServer的构造中会调用
ServletContextInitializer的onStartup(ServletContext servletContext)方法
在getWebServer方法中会实例化一个TomcatWebServer对象进行返回,在TomcatWebServer的构造中会调用
ServletContextInitializer的onStartup(ServletContext servletContext)方法
1. 设置spring根上下文到ServletContent的属性中,属性名为org.springframework.web.context.WebApplicationContext.ROOT
属性值为SC,并为SC#servletContext属性设置
属性值为SC,并为SC#servletContext属性设置
2. 注册应用作用域
1. 通过ServletContent构造一个ServletContextScope对象appScope
2. 将appScope添加到DF#scope Map中
3. 将appScope添加到ServletContent属性中
3. 注册Servlet的一些单例bean,如servletContext,contextParameters,contextAttributes等
4. 获取所有ServletContextInitializer bean
1. 在DF中查找符合ServletContextInitializer类型的bean进行加载,此处会加载DispatcherServletRegistrationBean
该bean是在DispatcherServletAutoConfiguration中进行引入的,而DispatcherServletAutoConfiguration
是在spring.factories中被引入的
该bean是在DispatcherServletAutoConfiguration中进行引入的,而DispatcherServletAutoConfiguration
是在spring.factories中被引入的
如果有引入springsecurity,则DelegatingFilterProxyRegistrationBean就是在这一环节被加载
然后在后面执行onStart方法的时候会将DelegatingFilterProxy过滤器添加到servlet上下文中
然后在后面执行onStart方法的时候会将DelegatingFilterProxy过滤器添加到servlet上下文中
2. 主要是从DF中加载Servlet,Filter,EventListener 类型的bean,然后包适配成RegistrationBean
所以我们自定义一个Filter类然后加上@Component注解也是会被加载到servlet上下文中
所以我们自定义一个Filter类然后加上@Component注解也是会被加载到servlet上下文中
3. 将上两步收集的bean排序后放入List<ServletContextInitializer> sortedList属性中供后面循环执行onStart()方法
5. 循环调用上一步中bean的onStart()方法,将各自bean中的Servlet/Filter/Listener注册到servlet上下文中
3. 和#2.7.1.2.4中执行的逻辑差不多,只是现在servletContent是有值的,会替换environment中设置的servletContextInitParams
10. 注册监听器
registerListeners();
registerListeners();
1. 将#1.5中获取到的那些监听器添加到SimpleApplicationEventMulticaster#applicationListeners集合中
在#2.6.9.1中有将#1.5中的那些监听器添加到SC#applicationListeners中,所以此处getApplicationListeners方法能获取到#1.5中的监听器
正因为将这些监听器添加到了SimpleApplicationEventMulticaster中,所以#1.5中的那些监听器也能监听到SC中广播的事件
在#2.6.9.1中有将#1.5中的那些监听器添加到SC#applicationListeners中,所以此处getApplicationListeners方法能获取到#1.5中的监听器
正因为将这些监听器添加到了SimpleApplicationEventMulticaster中,所以#1.5中的那些监听器也能监听到SC中广播的事件
2. 从DF中查找ApplicationListener类型的bean名称添加到SimpleApplicationEventMulticaster#applicationListenerBeans集合中
3. 判断SC的earlyApplicationEvents属性中是否有早期应用事件,有则直接发布,并清空earlyApplicationEvents属性
11. 实例化非延迟加载的单例bean
finishBeanFactoryInitialization(beanFactory);
finishBeanFactoryInitialization(beanFactory);
1. 设置初始化上下文转换服务,在#2.6.2中已经设置过了,所以此处不会再设置
2. 将DF中LoadTimeWeaverAware类型的bean进行实例化
3. 停止使用临时的类加载器
4. 冻结所有的bean定义,不再允许修改
5. 实例化bean定义
beanFactory.preInstantiateSingletons();
beanFactory.preInstantiateSingletons();
1. 根据DF#beanDefinitionNames中的名称进行循环初始化
1. 如果当前bean定义不是RootBeanDefinition则先转为RootBeanDefinition进行返回供后面实例化
同时添加到DF#mergedBeanDefinitions中供下次直接获取
同时添加到DF#mergedBeanDefinitions中供下次直接获取
2. 只对非抽象类非延迟加载的单例bean定义进行实例化
如果是工厂bean则通过&+bean名称去getBean实例,获取到的是bean工厂本身实例
如果该工厂bean是SmartFactoryBean实例且工厂bean的isEagerInit()方法返回值为true则去getObject
如果该工厂bean是SmartFactoryBean实例且工厂bean的isEagerInit()方法返回值为true则去getObject
如果是普通bean则直接进行加载
getBean具体加载流程查看"doGetBean源码分析"
2. 对SmartInitializingSingleton类型的bean执行回调方法afterSingletonsInstantiated
用来在所有非lazy单例Bean实例化完成后做写事情,比如EventListenerMethodProcessor
在此时会将@EventListener注册的监听添加到SC事件发布器中
用来在所有非lazy单例Bean实例化完成后做写事情,比如EventListenerMethodProcessor
在此时会将@EventListener注册的监听添加到SC事件发布器中
12. 完成容器刷新后的一些其他事情
finishRefresh()
finishRefresh()
1. 清除一些上下文中的缓存,比如scanning的时的一些元数据缓存
clearResourceCaches();
clearResourceCaches();
2. 初始化生命周期处理器DefaultLifecycleProcessor,将它作为单例bean添加到bean 容器中
initLifecycleProcessor();
initLifecycleProcessor();
3. 调用上面处理器的onRefresh方法,这个方法会找出实现了SmartLifecycle接口的bean进行start方法的调用
getLifecycleProcessor().onRefresh();
getLifecycleProcessor().onRefresh();
4. 发布ContextRefreshedEvent事件
publishEvent(new ContextRefreshedEvent(this));
publishEvent(new ContextRefreshedEvent(this));
5. 把当前容器上下文,注册到MBeanServer,这样可以通过就consule,VisualVM查看MBean等信息
LiveBeansView.registerApplicationContext(this);
LiveBeansView.registerApplicationContext(this);
1. 往MBeanServer中注册了LiveBeansView对象,其中保存了属性applicationContexts
2. 将SC上下文对象添加到applicationContexts中
SpringApplicationAdminJmxAutoConfiguration对注册SpringApplicationAdminMXBeanRegistrar bean
该bean中有个内部类SpringApplicationAdmin,该内部类实现了SpringApplicationAdminMXBean
SpringApplicationAdminJmxAutoConfiguration对注册SpringApplicationAdminMXBeanRegistrar bean
该bean中有个内部类SpringApplicationAdmin,该内部类实现了SpringApplicationAdminMXBean
8. 广播ApplicationStartedEvent事件
listeners.started(context);
listeners.started(context);
9. 回调ApplicationRunner或CommandLineRunner bean的run方法
callRunners(context, applicationArguments);
callRunners(context, applicationArguments);
0 条评论
下一页