getBean(String name)
昨天我们讲了单例实例化的时候会先判断是否是FactoryBean
类型的,是的话会进行相应处理,但是没讲最关键的getBean
,现在我们就开始讲这个,可能需要很多个篇幅,里面涉及了很多东西。废话不多说,我们开始吧。这些是我们要进行实例化的单例:
但是前面有一些已经被创建出来了,可以直接获取:
其实我们就只要关心我们自定义的两个对象:
我们开始吧:
doGetBean开始获取bean
我们来看下这个方法的参数:
name 就是bean名字
requiredType 表示需要的类型,如果有类型,创建后会进行类型转换
args 表示参数,也就是构造方法的参数
typeCheckOnly 表示只是做检查,并不是真的要用,这个会影响一些逻辑
因为代码比较长,我们分段来分析比较好,就保留和核心的代码:
doGetBean分段1
首先判断单例存在,且没有参数,这个时候还不能直接返回,还要做一些处理,因为传进来的名字可能是FactoryBean
本身,也就是name=&beanName
。
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//获取规范的名字
final String beanName = transformedBeanName(name);
Object bean;
//检查是否手动注册了单例
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {//存在单例了
...
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
AbstractAutowireCapableBeanFactory的getObjectForBeanInstance
这个方法有两个重要的参数name
和beanName
,name
是指传进来的名字,可能是FactoryBean
本身的名字,有&
前缀,也可能是一般的bean
名字,beanName
是规范后的名字,去掉了&
前缀,所以要进行处理。比如这种:
@Override
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//如果有正在创建的bean要建立以来关系,后面讲
String currentlyCreatedBean = this.currentlyCreatedBean.get();
if (currentlyCreatedBean != null) {
registerDependentBean(beanName, currentlyCreatedBean);
}
return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
}
AbstractBeanFactory的getObjectForBeanInstance
最后调用父类的处理方法,会下判断name
是不是FactoryBean
自身的名字,如果是,就判断beanInstance
是不是FactoryBean
类型的,是的话就直接返回,也就是说,要找的就是FactoryBean
自身,而不是他创建的bean
。如果不是FactoryBean
自身的名字,类型也不是FactoryBean
,那就普通的单例,直接返回。否则就是说明应该获取的是FactoryBean
创建的bean
。如果RootBeanDefinition
不为空的话,设置FactoryBean=true
,否则就从FactoryBean
的缓存中获取,如果获取到就直接返回,否则就要创建,然后返回。
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
if (BeanFactoryUtils.isFactoryDereference(name)) {//是否是FactoryBean名字的前缀
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {//不是FactoryBean的话名字有&会报异常
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {//不是FactoryBean就直接返回
return beanInstance;
}
//创建FactoryBean中的bean
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {//从FactoryBean的缓存中获取
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
if (mbd == null && containsBeanDefinition(beanName)) {//mbd没定义,但是FactoryBean是有定义的,获取mbd
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
getCachedObjectForFactoryBean从缓存里获取
factoryBeanObjectCache
就是FactoryBean
创建的bean
的缓存,创建一次后会进行缓存,下次直接拿。
@Nullable
protected Object getCachedObjectForFactoryBean(String beanName) {
return this.factoryBeanObjectCache.get(beanName);
}
getObjectFromFactoryBean创建bean
这里就是FactoryBean
创建bean
的过程。如果FactoryBean
是单例,且已经创建出来了,先从缓存里获取看看,如果存在直接返回。如果不存在就进行doGetObjectFromFactoryBean
创建,其实就是调用了getObject()
获取对象。这里又做了一次从缓存中获取,感觉挺奇怪的,前面已经获取不存在了,这里怎么又能存在,其实是因为getObject()
创建的时候可以自定义,可能有处理器处理,可能会对factoryBeanObjectCache
进行设置,所以这里还要判断一次,如果存在的话,就应该获取存在的,而不是刚创建的,这样的话处理器才算是有扩展的功能,否则处理了也等于没用。如果没有缓存存在,判断是否是否需要处理,其实这里说的就是不是合成的对象!synthetic
,比如AOP
的advice
通知就算是合成的,一般的对象都不合成的,如果需要处理,但是是正在创建中的单例,直接返回不处理,否则要进行处理器处理,最后放进缓存。如果是原型的话每次都创建一个新的。
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {//需要处理
if (isSingletonCurrentlyInCreation(beanName)) {//直接返回
return object;
}
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);//进行后置处理器处理
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {//如果包含了FactoryBean,就将创建的对象缓存
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {//FactoryBean是原型的话
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
doGetObjectFromFactoryBean
其实没别的东西,就是调用getObject()
创建对象,如果返回null的话,就封装成一个NullBean
。
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
...
object = factory.getObject();//调用自定义的FactoryBean的getObject获取对象
...
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {//如果是正在创建的FactoryBean,还没能获得bean,就报异常
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}
beforeSingletonCreation和afterSingletonCreation
这个就是标记下,正在创建这个bean
,创建处理完了就清除标记。
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);//没有在排除范围里内且添加不成功,可能就是循环引用了
}
}
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
postProcessObjectFromFactoryBean对创建出来的bean进行处理器处理
就是进行BeanPostProcessor
的postProcessAfterInitialization
处理,也就是可以扩展的地方。
@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
return applyBeanPostProcessorsAfterInitialization(object, beanName);
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
实战例子
测试例子:
没有设置原型:
设置了原型:
可见在FactoryBean
上设置了@Scope("prototype")
会影响创建的bean
。
果然讲细了没多少东西好讲,但是不讲清除直接跳过去等于没学什么,走马观花,到头来遇到问题还是得深入探究,学东西还是有点研究精神好。剩下的下篇继续吧。
好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。