文章目录
前几篇我们聊完了Bean初始化的前置步骤,也就是后面各个节点的处理器已经准备完毕了,下面就等着人去触发它们了。
这一篇我们就一起来看看,各个节点都分别在怎么样的一个时间上面执行。
preInstantiateSingletons()
这个方法就是实例化单例对象的入口,
它的内部可以看成两步:
- 初始化所有单例对象
- 唤醒SmartInitializingSingleton接口的方法
这里也可以看出,如果你需要在所有单例都创建完毕之后去做一些事情可以去实现SmartInitializingSingleton。
初始化所有单例对象
我还是拆分细点讲,如果上来就一大段代码,估计各位同学会瞬间失去耐心。
实例化也分成了两步,
- 对于实现了FactoryBean的实例化
- 普通Bean的实例化
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//非抽象,单例,非延迟加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {...}
else {getBean(beanName);}
}
FactoryBean的实例化
这个接口的作用是什么呢?其实它相当于一个小型的Bean工厂,给开发者提供一种更便捷的方式创建Bean。
比如说,你这个Bean有些东西需要通过查询数据库才能组装好,这时候就可以用这个接口,在内部通过编码的方式组装你的Bean。
Spring对于实现了FactoryBean的类所对应的实例,在BeanFactory中的name是”&”+beanName。
例如这样
public class TestFactoryBean implements FactoryBean<T>
那么BeanFactory中的name存放的就是“&TestFactoryBean”,如果我们通过“TestFactoryBean”这个名称去BeanFactory中获取,将会调用其getObject方法。
所以这里对FactoryBean要进行处理,在name前面添加一个&符号,然后在访问getBean方法创建Bean,也就是说最终会和创建普通Bean的实例流程保持一致。
普通Bean的实例化 (doGetBean)
接下来我们来看下普通Bean的实例化流程
- 通过beanName获取单例对象
- 如果存在则,判断是否是FactoryBean,如果是则返回getObject,否则返回它本身。
- 如果不存在,则实例化。
- 对创建的实例类型与需求的类型进行比较,不匹配则抛出异常
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null){
...
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {...}
if (requiredType != null && !requiredType.isInstance(bean)){...}
return (T)bean;
我们着重关注下第三步
- 自身是否有父BeanFactory,如果有则通过父BeanFactory加载。
- 检测当前bean是否有@DependsOn注解,如果有,先加载注解中的Bean。
- 根据Scope进行实例化(本篇文章与后续文章只分析单例模式,原型和其它模式各位同学可以自行去学习)
//如果有父类工厂,并且自身的BeanDefinition不包含,则通过父类进行加载
if (parentBeanFactory != null && !containsBeanDefinition(beanName)){...}
//获取当前Bean需要在某个Bean实例化之后才实例化
//通过注解@DependsOn来控制,不能在@DependsOn中相互写对方,会直接抛出异常,因为会导致这段代码死循环
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {...}
//单例模式
if (mbd.isSingleton()){...}
//原型模式
else if (mbd.isPrototype())
//其它模式
else {...}
其中单例模式
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
//创建bean
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
//应该很熟悉,判断是否是FactoryBean 并返回对应实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
由于getSingleton内部都是一些判断,我们这里就直接分析createBean的内部流程。
createBean()
在创建Bean内部分为了两步,
- 通过特殊手段创建Bean并返回
- 通过正常手段创建Bean并返回
//步骤一
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
...
//步骤二 看过源码的应该比较熟悉这个方法doCreateBean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
接下来我们就来看看这步骤一究竟怎么个特殊法。
其实就是找到所有实现了InstantiationAwareBeanPostProcessor
的方法(其继承于BeanPostProcessor),然后唤醒postProcessBeforeInstantiation()
方法,如果有返回值,就以返回值作为Bean装载到BeanFactory中。
然后访问BeanPostProcess
的后置方法postProcessAfterInitialization()
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
//没有访问BeanPostProcessor的Before方法?
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//访问所有的InstantiationAwareBeanPostProcessor 如果返回了结果则直接返回
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
//唤醒BeanPostProcessor后置方法
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
异常手段看完了,接下来等我们下一章在来聊聊正常手段创建Bean。
唤醒SmartInitializingSingleton实例的方法
当所有单例对象都创建完毕之后,就会去容器中查找所有实现了SmartInitializingSingleton
接口的实例,并访问其afterSingletonsInstantiated
方法。
(某些同学可能使用过InitializingBean这个接口,但是你要明白,你在初始化的时候有可能其它的Bean并没有实例化完毕,所以有些操作是有风险的,如果你分不清这时间点到底对不对,保险的方式就是使用SmartInitializingSingleton
这个接口)
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
总结
也不知道说些什么,最近又是些糟心的事。 那就新年快了吧
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/121869.html