
在Spring启动之后,个人暂时将Spring注入Bean对象的过程分为3个大的步骤,分别是:
Bean的扫描→Bean的实例化→Bean的初始化。
第一步:Bean的扫描
在Spring启动的时候,AnnotationConfigApplicationContext的几种构造参数可以选择使用XML、配置类、包路径来进行扫描
//配置类扫描
ApplicationContext ac=new AnnotationConfigApplicationContext(AppConfig.class);
//配置文件XML扫描
ApplicationContext ac1 =new ClassPathXmlApplicationContext("Spring-rl.xml");
//直接包路径扫描
ApplicationContext ac2 =new AnnotationConfigApplicationContext("com.test");
本文下面以注解类为启动流程
AppConfig.Class 配置类:
package com.asop.app;
import org.springframework.context.annotation.ComponentScan;
/**
* @description:
* @author:19047590
* @date: Created in 2020-05-23 16:56
*/
@ComponentScan("com.asop")
public class AppConfig {
}
启动类:
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(AppConfig.class);
}
}
AnnotationConfigApplicationContext 在启动的时候的构造函数
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
//在初始化的时候,直接将appConfig放入到bdMap中。否则就是不能执行了
//这个方式就用来完成Spring中的初始化需要的一些基本的bd
register(componentClasses);
//Bean的注入
refresh();
}
/**
* Create a new AnnotationConfigApplicationContext that needs to be populated
* through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
*/
public AnnotationConfigApplicationContext() {
//reader 对于外部的beanDefinition进行读取的
//父类的构造方法 创建一个读取注解的Bean定义读取器
this.reader = new AnnotatedBeanDefinitionReader(this);
//可以用来扫描包或者类 然后转化成bd
//实际上扫描包工作的时候不是scanner这个对象完成的
//是Spring自己new一个ClassPathBeanDefinitionScanner
//这里的scanner仅仅是为了能够在外部调用AnnotationConfig
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
因为AnnotationConfigApplicationContext继承了GenericApplicationContext。所以在执行AnnotationConfigApplicationContext的构造函数的时候时候首先执行了GenericApplicationContext的构造函数,创建了beanFactory
public GenericApplicationContext() {
//创建了beanFactory
this.beanFactory = new DefaultListableBeanFactory();
}
在创建完成BeanFactory之后,执行AnnotationConfigApplicationContext的构造函数,创建了AnnotatedBeanDefinitionReader读取注解的Bean定义读取器。
ClassPathBeanDefinitionScanner(为了能够在外部调用AnnotationConfig)。
以上执行完成了AnnotationConfigApplicationContext的无参构造函数。
接着执行有参构造中的方法:register()方法
register方法主要是将AppConfig.Class类解析为AnnotatedGenericBeanDefinition类后注入到BeanFactory当中去。
注册到BeanFactory的核心的代码
//AnnotatedGenericBeanDefinition abd 继承了GenericBeanDefinition 用来处理注解类,注册为BeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
abd.setInstanceSupplier(supplier);
abd.setScope(scopeMetadata.getScopeName());
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//将自定义注解类注册进去。
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

refresh() 方法,进行Bean对象的扫描和注入。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从
//子类的refreshBeanFactory()方法启动
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//为BeanFactory配置容器特性,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//为容器的某些子类指定特殊的BeanPost事件处理器
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//调用所有注册的BeanFactoryPostProcessor的Bean
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//为BeanFactory注册BeanPost事件处理器.
//BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
//初始化信息源,和国际化相关.
initMessageSource();
// Initialize event multicaster for this context.
//初始化容器事件传播器.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
//调用子类的某些特殊Bean初始化方法
onRefresh();
// Check for listener beans and register them.
//为事件传播器注册事件监听器.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//初始化所有剩余的单例Bean
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
//初始化容器的生命周期事件处理器,并发布容器的生命周期事件
finishRefresh();
}
invokeBeanFactoryPostProcessors 扫描出AppConfig中的指定的路径下的所有需要注册的Bean,并存放在BeanDefinitionMap中。
首先处理BeanDefinitionRegistryPostProcessor,处理完成之后处理开始扫描其它的类。 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);该方法中的scanCandidateComponents会根据AppConfig中的包路径来对编译好的Class文件进行扫描
scanCandidateComponents(String basePackage).
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
//将该路径下的类转化为Spring自定义的Resource类。
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);

接下来会for循环来判断该类是否是需要注册的对象
for (Resource resource : resources) {
if (resource.isReadable()) {
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
if (isCandidateComponent(metadataReader)) {
//当前类是否有@Component注解或者是用户扩展的自定义注解
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
//是否满足其他条件
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
candidates.add(sbd);
}
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
for (TypeFilter tf : this.excludeFilters) {
//AppConfig中的ComponentScan是否配置了需要排除的包
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}
for (TypeFilter tf : this.includeFilters) {
//注解扩展 默认有@Component 然后可以有用户自定义的扩展的注解
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
return false;
}
如果符合条件,会添加到LinkedHashSet集合candidates中。
然后将扫描出来的类转化为BeanDefinitionHolder类型的Set集合并返回
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//将扫描完成的beanDefinitions注入到BeanDefiintionMap中
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
往下执行后会执行扩展的BeanFactoryPostProcessor
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
//这里就可以执行用户自己扩展的BeanFactoryPostProcessor
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
以上步骤就是Spring启动之后扫描Bean的主要的流程
bean的实例化及初始的过程
bean的实例化、初始化过程主要是针对于@Scope类型是单例模式(singleton)的bean。
主要是经过了8次后置处理器的方法后完成了实例化、初始化。其中前6次后置处理器是完成实例化的,后两次是完成初始化的功能。
1、InstantiationAwareBeanPostProcessor bp.postProcessBeforeInstantiation
主要调用的实现方法AbstractAutoProxyCreator.postProcessBeforeInstantiation
主要是判断当前类是否需要aop的代理。如果需要的话,并且当前的bean不为空的话,生成对应的代理对象,但是这里一定为空.因为还没有实例化Bean对象。所以只是做了advisedBeans缓存
postProcessBeforeInstantiation ->之后会调用doCreateBean来创建bean对象。
2、determineConstructorsFromBeanPostProcessors 里面调用了第二次后置处理器
SmartInstantiationAwareBeanPostProcessor bp.determineCandidateConstructors
来决定返回哪些方法 选择使用哪个构造器,这个后置处理器处理的主要是使用了@Autowired注解的(该构造方法的入参必须是Spring在Ioc容器中可以找到所有的对象,如果有一个找不到的话 就会报错)
当没有使用@autoWired注解选择对应的构造函数的时候,Spring这个时候会判断当前对象的自动注入模型。如果是1 no的话,那么就是默认使用无参构造,
如果是3的话,就是byType。那么会使用贪婪模式,选择最长的构造函数(同上,需要满足该构造函数的对象都在Spring容器中。)
3、applyMergedBeanDefinitionPostProcessors 方法第三次调用Bean的后置处理器. 这个后置处理器 涉及到了BeanDefinition对象的合并和使用 合并主要是指在SpringXML文件中有配置的Bean使用了
MergedBeanDefinitionPostProcessor processor.postProcessMergedBeanDefinition
这个后置处理器主要是找到当前的Bean需要注入的属性 主要有@AutoWired注解和@Resource注解注入的属性。 injectionMetadataCache在后面是相同处理的。
@Resource在Spring中是根据CommonAnnotationBeanPostProcessor找到的
@AutoWired在Spring中是根据AutowiredAnnotationBeanPostProcessor找到的
4、第四次调用后置处理器 循环依赖 提前暴露一个对象Bean工厂 然后可以处理Bean的Aop的内容
SmartInstantiationAwareBeanPostProcessor bp.getEarlyBeanReference
根据第一步判断当前类是否需要aop代理,然后需要的话,根据类是否强制优化 是否是单独的类或者是实现了接口的类 来判断是使用JDK动态代理或者是CGLIB动态代理来生成代理对象
在完成了动态代理之后,在Spring容器中存放的就不是和普通类相同的Bean,而是代理对象。
5、第五次调用后置处理器InstantiationAwareBeanPostProcessor bp.postProcessAfterInstantiation
判断当前实现了InstantiationAwareBeanPostProcessor的接口是否都是需要要注入属性的 是的话返回true 不是的话 返回false 只要有一个不是的话 直接返回false 该对象就不注入属性
可以自己实现该接口 然后来阻止该对象进行注入。
6、InstantiationAwareBeanPostProcessor bp.postProcessProperties用来处理@Autowired注解和@Resource注解的属性。
完成扫描后和上面autowiring自动注入找到的属性值一起填充。注入的方式使用的是Java反射方法中的Filed.set方法
7、第七次调用后置处理器BeanPostProcessor postProcessBeforeInitialization方法 这个时候已经实例化结束
开始了初始化的工作 初始化前置方法 完成@PostConstruct注解方法 在执行完成之后 invokeInitMethods方法会执行实现了InitializingBean接口的afterPropertiesSet方法 所以两个方法有先后顺序
8、BeanPostProcessor postProcessAfterInitialization 初始化后置方法Spring主要用来执行aop方法

本文详细介绍了Spring启动后Bean的扫描、实例化和初始化过程。从Bean的扫描,包括通过注解类进行配置、构造函数的选择,到Bean的实例化,涉及InstantiationAwareBeanPostProcessor等多个后置处理器的作用,再到Bean的初始化,涵盖@PostConstruct注解方法和InitializingBean接口的afterPropertiesSet方法的执行。整个流程详细剖析了Spring管理Bean的生命周期。

被折叠的 条评论
为什么被折叠?



