前言
此篇是补充上篇未分析完的finishBeanFactoryInitialization部分
配合上篇食用效果更佳
finishBeanFactoryInitialization(beanFactory)
主要方法preInstantiateSingletons()遍历List beanNames
如果Bean 不是抽象&是单例&不是lazy
如果不是FactoryBean
getBean进入doGetBean 下面四张图都是
doGetBean.1
重点方法 getSingleton 大致执行如下
//先从缓存中取 第一次进来时没有值的
Object singletonObject = this.singletonObjects.get(beanName);
//存在 则return
if(singletonObject!=null) return;
//解决循环依赖
beforeSingletonCreation(beanName);
//真正创建bean
singletonObject = singletonFactory.getObject();
afterSingletonCreation(beanName);
//加入缓存
addSingleton(beanName, singletonObject);
return singleObject
复制代码
真正创建Bean是createBean() 如果是bean是多例
//this.prototypesCurrentlyInCreation.set(beanName)
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
//this.prototypesCurrentlyInCreation.remove()
afterPrototypeCreation(beanName);
复制代码
单例多例创建Bean都会调用到createBean
真正创建Bean是createBean()//一般用于创建aop代理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
//如果上边没有代理 这里会真正开始创建
Object beanInstance = doCreateBean(beanName, mbdToUse, args)
复制代码
createBean->resolveBeforeInstantiation
doCreateBean.1 doCreateBean.2 doCreateBean.3 走向如下面流程图 doCreateBean->createBeanInstanceapplyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
bp instanceof MergedBeanDefinitionPostProcessor -> bp.postProcessMergedBeanDefinition(mbd, beanType, beanName)
populateBean
为刚刚实例化好的Bean进行属性等赋值
-
BeanWrapper为null直接报错或者return
-
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
官方的解释是:让用户可以自定义属性注入。比如用户实现一 个 InstantiationAwareBeanPostProcessor 类型的后置处理器,并通过 postProcessAfterInstantiation 方法向 bean 的成员变量注入自定义的信息。当然,如果无 特殊需求,直接使用配置中的信息注入即可。另外,Spring 并不建议大家直接实现 InstantiationAwareBeanPostProcessor 接口,如果想实现这种类型的后置处理器,更建议 通过继承 InstantiationAwareBeanPostProcessorAdapter 抽象类实现自定义后置处理器
- 这里会出现一个Spring的内部processor:AutowiredAnnotationBeanPostProcessor 执行下去 进入postProcessProperties 首先找出所有的注解包括@Value @Autowired然后进行调用inject方法进行赋值 最终是通过反射实现最终赋值
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
复制代码
applyPropertyValues(beanName, mbd, bw, pvs);
将属性应用到 bean 对象中
-
检测属性值列表是否已转换过的,若转换过,则直接填充属性,无需再次转换
-
遍历属性值列表 pvs,解析原始值 originalValue,得到解析值 resolvedValue
-
对解析后的属性值 resolvedValue 进行类型转换
-
将类型转换后的属性值设置到 PropertyValue 对象中,并将 PropertyValue 对象存入 deepCopy 集合中
-
将 deepCopy 中的属性信息注入到 bean 对象中
流程图:
exposedObject = initializeBean(beanName, exposedObject, mbd)
余下的初始化工作
invokeAwareMethods(beanName, bean)若 bean 实现了 BeanNameAware、BeanFactoryAware、BeanClassLoaderAware 等接口,则向 bean 中注入相关对象 applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
实例化前执行后置处理器对应的postProcessBeforeInitialization方法
invokeInitMethods(beanName, wrappedBean, mbd)
- 判断是否是InitializingBean的实现,执行接口规定的初始化afterPropertiesSet
- 执行invokeCustomInitMethod,方法大致是
找出所有初始化方法(@Bean initMethod属性指定的方法) mbd.getInitMethodName() 对应去执行
执行 bean 初始化后置操作,AOP 会在此处向目标对象中织入切面逻辑
如果是FactoryBean
FactoryBean一直都没怎么用过 所以自己写了demo用下
@Autowired
private Student2 student2;
复制代码
debug一下 查看下执行过程
发现它是在Student2.Class是在 populateBean的时候调用processor进行inject时被实例化的,此时发现是FactoryBean就直接被调用了getObject 拿到这个bean 也就是说,一开始被实例化的只有MyFactoryBean这个类,而没有Student2这个类MyFactoryBean此时 beanName=&myFactoryBean
总结
这次Spring ioc源码看了我好几天,收获还是挺大的,也总结
- 查看源码前提:是必须要知道怎么用
- 如果实在看不懂,可以google找再总结
- 有时有些很底层的可以先跳过,先直接到知道必将执行的方法打断点,由后往前看方法栈debug(如FactoryBean这部分)
最后关于Spring总结 主要按着下面四点去看 1)、Spring容器在启动,先保存Bean定义信息
- xml注册bean
- 注解注册Bean
2)、Spring容器会在XX的情况下创建Bean
- 用到这个bean的时候 去创建 *finishBeanFactoryInitialization 统一创建bean
3)、后置处理器 *每一个Bean创建完成 会使用处理器处理
- AutowiredAnnotationBeanPostProcessor 处理自动注入
- XXXPostProcessor
4)、事件驱动模型 *ApplicationListener 事件监听 *ApplicationEventMulticaster 事件派发