目录
- Spring Bean 从扫描到创建
- 扫描流程 class 到 BeanDefinition
- 引入
- 扫描:ClassPathBeanDefinitionScanner
- doScan
- findCandidateComponents(basePackage)
- registerDefaultFilters()
- this.registry
- 创建流程 BeanDefinition 到 Bean
- 统一 BeanDefinition 类型
- finishBeanFactoryInitialization(beanFactory);
- getMergedLocalBeanDefinition(beanName)
- 创建Bean
- doGetBean
- 转化BeanName(transformedBeanName(name))
- createBean(beanName, mbd, args)
- resolveBeanClass(mbd, beanName)
- createBeanInstance(beanName, mbd, args)
- populateBean(beanName, mbd, instanceWrapper)
- initializeBean(beanName, exposedObject, mbd)
Spring Bean 从扫描到创建
扫描流程 class 到 BeanDefinition
引入
上一个分析文章中我们知道从Class到一个Bean中间是需要把Class先创建成BeanDefinition
然后由Spring控制在不同的时机用不用的方法依据BeanDefinition转化为Bean供我们使用
那么Class到BeanDefinition的流程是什么?
先说结论这个过程主要发生在
ClassPathBeanDefinitionScanner : 扫描读取Class文件为Resource对象
扫描:ClassPathBeanDefinitionScanner
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan
这个方法就是扫描包中的文件,把文件加载成Resource对象的并注册成为BeanDefinition的
doScan
分析下细节:
遍历basePackages : basePackage {
查找到所有符合要求的BeanDefinition(findCandidateComponents(basePackage)) : candidates
遍历所有的 BeanDefinitions : beanDefinitions {
解析:Scope.class
获取beanName
if instanceof AbstractBeanDefinition : 执行postProcessBeanDefinition:
1. 设置默认值
setLazyInit
setAutowireMode(defaults.getAutowireMode());
setDependencyCheck(defaults.getDependencyCheck());
setInitMethodName(defaults.getInitMethodName());
setEnforceInitMethod(false);
setDestroyMethodName(defaults.getDestroyMethodName());
setEnforceDestroyMethod(false);
2. setAutowireCandidate
if instanceof AnnotatedBeanDefinition : 解析 @Lazy、@Primary、@DependsOn、@Role、@Description
if (this.registry是否存在beanName) {
注册BeanDefinition到this.registry
}
}
}
findCandidateComponents(basePackage)
if 没有 编写索引文件 那么进入 scanCandidateComponents(basePackage);
scanCandidateComponents(basePackage) {
路径转化 包名转化为三部分组成的路径
1. classpath*:
2. 包名中的 "." 替换为 "/"
3. /**/*.class
扫描路径中的class文件为 Resource[] resources
遍历 resources :: resource {
判断是否符合条件
1. excludeFilters 符合任意一个则排除(默认为空)
2. includeFilters 符合任意一个则包含(默认registerDefaultFilters())
3. 如果命中include 继续检查是否使用@Conditional
if (没排除,且包含) {
组装ScannedGenericBeanDefinition sbd
1. this.beanClass = beanClassName;
2. this.resource = resource;
3. this.source = source;
判断是否可以创建Bean
1. 非内部类的Class
2. &&(是具体类 || 是抽象类但是方法上有@Lookup)
if (判断通过) {
添加到候选池中 candidates
}
}
}
}
registerDefaultFilters()
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#registerDefaultFilters
添加了三个includeFilter
- org.springframework.stereotype.Component
- javax.annotation.ManagedBean
- javax.inject.Named
this.registry
这里的 registry 并不是 AnnotationConfigApplicationContext 虽然 AppContext本身也是Registry
但是这里的 registry 是
org.springframework.context.annotation.ComponentScanAnnotationParser#parse 中 new 出来的
ClassPathBeanDefinitionScanner 中带有的 org.springframework.beans.factory.support.DefaultListableBeanFactory
而在 DefaultListableBeanFactory 维护了一个 Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
- 是否存在 : this.beanDefinitionMap.containsKey(beanName);
- 注册:this.beanDefinitionMap.put(beanName, beanDefinition);
创建流程 BeanDefinition 到 Bean
统一 BeanDefinition 类型
finishBeanFactoryInitialization(beanFactory);
统一为:RootBeanDefinition
创建非懒加载单例bean
扫描所有的BeanDefinition创建Bean在:
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
遍历beanDefinitionNames : beanNames : beanName {
根据beanName 组装 和合并BenaDefinition(RootBeanDefinition) : bd
//注意这里判断的是是不是抽象的BeanDefinition 而不是判断的是不是一个抽象类
//抽象的BeanDefinition 在自定义BeanDefinition的时候可以提供一个些公共的属性
if (bd 不是抽象的 && 是单例的 && 是懒加载的) {
if (是工厂Bean(FactoryBean)) {
//这里已经创建一个beanName的Bean了 创建的对象是Class对应的对象
//也就是说在容器创建的是否并没有创建getObject指定的对象
//getObject指定的对象是在使用的时候创建的
Object bean = getBean(FACTORY_BEAN_PREFIX(&) + beanName);
} else {
//这里就会真的去创建Bean了
getBean(beanName);
}
}
}
重新遍历 beanNames : beanName {
根据beanName 获取对象
if (instanceof SmartInitializingSingleton) 则执行
smartSingleton.afterSingletonsInstantiated();
smartInitialize.end();
}
//这里算是生命周期扩展的一个补充 在所有非懒加载单例Bean初始化后执行的2个方法
getMergedLocalBeanDefinition(beanName)
根据beanName组装合并BenaDefinition(RootBeanDefinition)
最终执行逻辑的是:
org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition(java.lang.String, org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.config.BeanDefinition)
缓存池中获取mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd == null) {
if (bd.getParentName() == null 且 不是 RootBeanDefinition) {
mbd = 就根据现有的BeanDefinition创建RootBeanDefinition
}
if (bd.getParentName() != null) {
mbd = 就把父子融合创建RootBeanDefinition
1. 根据父BeanDefinition创建RootBeanDefinition
2. 在根据子类BeanDefinition覆盖对应的信息
}
}
//所以在Spring中常用的是融合后的RootBeanDefinition池子
//这里也起到归类的作用
//比如扫描出来的BeanDefinition是ScannedGenericBeanDefinition
//而根据配置类创建出来的是AnnotatedGenericBeanDefinition
//最终都在这里转化为RootBeanDefinition供创建Bean使用
创建Bean
doGetBean
分析的代码为:
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
转化BeanName(transformedBeanName(name)) : beanName
//查看缓存中是否已经有beanName对应的实例了
Object sharedInstance = getSingleton(beanName);
//getObjectForBeanInstance 注释说了可以返回本身 或者 返回FactoryBean 时创建的对象
if (sharedInstance != null ) {beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);}
if (sharedInstance == null ) {
if (curVal = this.prototypesCurrentlyInCreation.get() 且 curVal等于或者包含 beanName) { 认为循环依赖,报错}
获取父Bean工厂:parentBeanFactory
if (parentBeanFactory != null 且 自身没有对应的BeanDefinition){
//这里把beanName 恢复了一下 这个name是之前没有处理前的name,有可能带&
//这里如果带了& 就用带& 处理
String nameToLookup = originalBeanName(name);
返回 parentBeanFactory.getBean(nameToLookup, args);
}
if (parentBeanFactory == nul){
//获取RootBeanDefinition 因为在上一步已经有缓存了这里直接拿到了
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
if (mbd.getDependsOn()有值) {创建DependsOn内的Bean}
//不同scope调用不同的创建策略
case 单例 :
sharedInstance = getSingleton(beanName, 创建Bean(createBean(beanName, mbd, args)));
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
break;
}
//这里其实就是看下Bean实例是不是你需要的类型
//也就是 getBean(name, class)中的class类型
//如果不是则调用Converter尝试进行转化
return 适配BeanInstance
}
转化BeanName(transformedBeanName(name))
if (& 开头) {把所有的&去掉}
//这里就是查到别名映射的最终的BeanName
while(resolvedName = this.aliasMap.get(canonicalName) 且 resolvedName != null) {
canonicalName = resolvedName;
}
createBean(beanName, mbd, args)
真实的创建Bean的逻辑
分析的代码是:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
获取 Class 的对象 : resolvedClass (resolveBeanClass(mbd, beanName))
//这里为啥要复制一个出来用 我的想法是避免别的地方修改原有的对象对我造成影响
重新赋值一个 RootBeanDefinition :mbdToUse
//这里之前setBeanClass是把类的name放进去了 在这里改为把Class对象放进去
mbdToUse.setBeanClass(resolvedClass);
//beforeInstantiationResolved 这个属性是RootBeanDefinition自己的 Spring默认是没有赋值的
if (mbd.beforeInstantiationResolved == null || == true) {
//这里InstantiationAwareBeanPostProcessors是有值的
if(hasInstantiationAwareBeanPostProcessors()) {
获取目标Class类型 = mbd.getTargetType() : this.resolvedTargetType
//这里是给自定义Bean一个机会 如果这里有任何一个返回就直接作为最终Bean了
//Spring 默认在这里没有返回的
遍历处理器 InstantiationAwareBeanPostProcessor:bp{
Object result = bp.postProcessBeforeInstantiation(beanClass, beanName)
if (result != null) {
//这里赶紧再执行下初始化后置处理器方法
//因为实例化已经被处理器拦截了 走不动后边了
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
//这个对象就是放在容器里的Bean了
return result ;
}
}
}
//没有被实例化前处理器拦截的化就进去正式的实例化
BeanWrapper instanceWrapper = null;
if(是单例) {instanceWrapper=从factoryBeanInstanceCache获取一下}
if(instanceWrapper == null){
instanceWrapper = 创建Bean实例(createBeanInstance(beanName, mbd, args))
}
//到这里 instanceWrapper 就默认不是null了 因为后续就直接用了
mbd.resolvedTargetType = instanceWrapper.getWrappedClass();
//这里的处理器是给修改 mbd 一个机会
遍历处理器 MergedBeanDefinitionPostProcessor :processor {
processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
//属性填充
populateBean(beanName, mbd, instanceWrapper);
//初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
//注册bean销毁相关
registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
}
resolveBeanClass(mbd, beanName)
根据className获取class
//这里其实beanClass还保存的ClassName 不是一个Class
if (mbd.beanClass instanceof Class) { return mbd.beanClass}
String className = mbd.beanClass;
evaluated = el表达式解析器解析处理下 className
if(className != null) {return beanClassLoader.loadClass(className);}
//到这里说明没有特别设置className那就正常解析
Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
this.beanClass = resolvedClass;
return resolvedClass;
createBeanInstance(beanName, mbd, args)
//这一次经过上边的解析 mbd.beanClass 已经是个对象所以直接返回了
获取 Class 的对象 : resolvedClass (resolveBeanClass(mbd, beanName))
//这里行为参数化 你要自定义了实例方法就用你设置的实例创建方法创建
if (mbd.getInstanceSupplier() != null) {return Supplier.get()}
//默认没有值
if (mbd.getFactoryMethodName() != null) {return 指定工厂方法创建}
//这里大致意思就是 如果 args传值就用传入的值来推断下带参构造方法实例化
if (args == null && mbd.resolvedConstructorOrFactoryMethod != null) {return autowireConstructor(beanName, mbd, null, null);}
//如果构造器上有@Autowired
遍历处理器 SmartInstantiationAwareBeanPostProcessor bp {
Constructor<?>[] ctors = bp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
if (ctors != null) {return autowireConstructor(beanName, mbd, ctors, args);}
//走到这里就是后置处理器没有设置 也没有带@Autowired 那就用配置的默认构造器
//这里Spring 还没想好咋实现 直接就是返回 null
if ((ctors = mbd.getPreferredConstructors()) != null) {return autowireConstructor(beanName, mbd, ctors, args);}
//到这里就是用 无参构造器创建了
return instantiateBean(beanName, mbd);
populateBean(beanName, mbd, instanceWrapper)
instanceWrapper 中包含了已经实例化的对象
遍历处理器 InstantiationAwareBeanPostProcessor bp {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
//如果到这里就阻断属性赋值流程了
return;
}
}
PropertyValues pvs = mbd.getPropertyValues();
//如果有后置处理器设置了PropertyValues 就把这个设置给pvs 默认是没有的
//但是这里有一个AutowiredAnnotationBeanPostProcessor会处理@Autowired、@Value
遍历处理器 InstantiationAwareBeanPostProcessor bp {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
pvs = pvsToUse;
}
if (pvs.isEmpty()) {return;}
initializeBean(beanName, exposedObject, mbd)
//这里提前处理了三个Aware
//BeanNameAware\BeanClassLoaderAware\BeanFactoryAware
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
遍历处理器 BeanPostProcessor processor {
Object current = processor.postProcessBeforeInitialization(result, beanName);
//current == null 直接 return
wrappedBean = current;
}
if (bean instanceof InitializingBean) {bean.afterPropertiesSet();}
if ((String initMethodName = mbd.getInitMethodName()) != null) {调用InitMethodName}
//AOP就是在这里把对象替换成了代理对象
遍历处理器 BeanPostProcessor processor{
Object current = processor.postProcessAfterInitialization(result, beanName);
//current == null 直接 return
wrappedBean = current;
}
return wrappedBean;