作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO
联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬
学习必须往深处挖,挖的越深,基础越扎实!
阶段1、深入多线程
阶段2、深入多线程设计模式
阶段3、深入juc源码解析
码哥源码部分
码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】
码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】
码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】
码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】
打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】
isFactoryBean(String name)根据名字判断是否是FactoryBean
我们继续上篇,上篇讲了getMergedLocalBeanDefinition
,以及为什么要用这个,本篇来讲后面的isFactoryBean
方法,怎么来判断一个beanName
是否是FactoryBean
类型。getBean
比较复杂,后面一起讲,暂时知道这个可以获取对象就好,本篇讲这部分:
@Override
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
String beanName = transformedBeanName(name);//获取转换后的名字
Object beanInstance = getSingleton(beanName, false);
if (beanInstance != null) {//如果已经是单例了,就判断是否是FactoryBean类型
return (beanInstance instanceof FactoryBean);
}
// 没有单例,看是否有bean定义,没有就看父类bean工厂
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
}
return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}
transformedBeanName转换后的名字
我们来看这个转换名字,其实跟上篇说的FactoryBean
名字相关,我们还是来看源码吧:
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
BeanFactoryUtils的transformedBeanName
首先判断是不是有&
前缀,没有就直接返回,说明不是FactoryBean
的名字,否则就从缓存里获取,然后把前缀&
去掉返回。
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
canonicalName取出原始名字
进行名字的规范化,其实就是取出原始名字,如果是别名就从映射中取原始名,是原始名字直接返回。
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
getSingleton(String beanName, boolean allowEarlyReference)获取单例
这个方法传入一个名字和是否允许早期引用,这个是为了解决循环依赖的问题,这个后面会讲,现在忽略就行。singletonObjects
是一个ConcurrentHashMap
,放已经创建好的单例,如果发现有创建好了,就直接返回,否则判断是否正在创建isSingletonCurrentlyInCreation
,earlySingletonObjects
是HashMap
,用来保存运行早期创建引用的单例,为了解决循环依赖。我们可能会奇怪,为什么earlySingletonObjects
不是ConcurrentHashMap
,其实因为他所有的操作,都是在synchronized
同步块中了,所以不需要了,而singletonObjects
则可以在没有同步块的地方使用。继续说,如果在earlySingletonObjects
也没找到,又是允许早期引用的,就从单例singletonFactories
工厂中获取一个工厂,其实就是一个可以获取对象的工厂,只要存在,就能通过getObject()
获取,然后放进earlySingletonObjects
,删除工厂,其实有循环引用的时候就可以派上用了,后面会说。
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
isSingletonCurrentlyInCreation是否正在创建中
singletonsCurrentlyInCreation
这个是个set存放正在创建的单例的名字,所以可以判断是否正在创建中。
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
isFactoryBean(String beanName, RootBeanDefinition mbd)根据名字和bean定义判断是否是FactoryBean
如果FactoryBean
单例没获取到,此时只能通过名字和bean
定义看是否是FactoryBean
了。如果定义本身定义了isFactoryBean
,那就直接返回结果,否则需要进行类型预测,他会进行反射,看看名字对应的类是否是FactoryBean
类型的,如果预测出来的类型是FactoryBean
,那就返回true
了,否则就false
。
protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
Boolean result = mbd.isFactoryBean;
if (result == null) {
Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
result = (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
mbd.isFactoryBean = result;
}
return result;
}
获取FactoryBean
如果发现名字是FactoryBean
类型的话,就会在名字前加前缀&
,然后去获取,获取完了判断是否是FactoryBean类型,是的话再判断是否需要理解创建FactoryBean
中的对象,如果是的话就直接获取名字,此时的名字是没有&前缀的,也就直接获取FactoryBean
的getObject()
方法创建的对象。当然如果名字不是FactoryBean
类型的话,就直接获取对象。
总结
这部分主要就是创建单例,如果发现是FactoryBean
类型的话,就获取FactoryBean,然后判断是否需要立即进行getObject()
方法创建的对象,需要的话就创建。如果不是FactoryBean
类型的话,就直接获取创建对象。