本文已参与「新人创作礼」活动,一起开启掘金创作之路。
1、前言
上文 Spring XML方式获取bean过程概览 讲解了XML方式获取bean的大概流程,这篇文章说下真正获取bean的前置操作。
2、从doGetBean开始
继续查看 现在User1 user = context.getBean(“user”, User1.class); 解析获取bean的过程。
- 获取通过name获取bean真实的beanName
- 使用beanName尝试从缓存中获取bean
- 如果从缓存中获取到,那么返回对应的实例。
- 如果没有从缓存中获取,判断是否是原型模式,如果存在循环依赖,直接报错
- 获取parentBeanFactory
- 如果parentBeanFactory不为空,尝试从parentBeanFactory 递归获取bean
- 如果为空,那么判断是否只对类型检测,那么会记录
- 将配置Xml 配置文件的GenericBeanDefination 转换成RootBeanDefination,如果指定beanName 那么会合并到父类的相关属性
- 之后判断是否存在依赖的bean,如果存在先对依赖对象进行注册并获取
- 判断定义bean是否是单例模式,如果是获取作用域是单例模式的情况bean
- 判断定义bean是否是原型模式,如果是获取作用域是原型模式的情况bean
- 如果不是单例和原型模式,那么获取作用域,并获取作用域下bean
- 检测最终获取的bean是否和需要的bean类型一致,如果一致那么返回或的bean
2.1、获取真正的beanName
final String beanName = transformedBeanName(name);
进入查看:
其实一共就两个步骤,第一处理特殊字符&,然后从aliasMap中获取真实beanName。
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
// 处理特殊字符
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;
});
}
public String canonicalName(String name) {
String canonicalName = name;
String resolvedName;
do {
resolvedName = (String)this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
} while(resolvedName != null);
return canonicalName;
}
2.2、从缓存中获取bean
Object sharedInstance = getSingleton(beanName);
进入查看具体实现:
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
@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;
}
这里主要是从缓存中获取bean实例。先从singletonObjects中获取,如果未获取到从earlySingletonObject获取,再未获取到那么从singletonFactories中获取。这也是获取bean的三级缓存。
其中 singletonObjects 是已经完成实例化的对象,earlySingletonObject 是经过代理但是没有对属性赋值的对象,singletonFactories 是缓存当前实例的工厂bean。
2.3、获取bean实例
这里其实不仅仅应用于从缓存获取成功后处理,而且未成功处理最后也是通过此方法获取实例bean。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
进入此方法实现:
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
这里其实主要是对普通bean和FactoryBean的区分,普通bean直接返回,作为FactoryBean需要特殊处理。
getCachedObjectForFactoryBean的作用是从factoryBeanObjectCache缓存中获取FactoryBean。
再后通过 getMergedLocalBeanDefinition 查看 是否存在继承关系bean并也存在实例化的情况,如果存在则进行合并。
示例: bean Person 和 继承了Person的bean PersonExt。 在XML配置文件中:
<bean class="com.fankf.spring.Person" name="p,p1" init-method="myInit" destroy-method="myDestory">
<property name="name" value="lisi"/>
</bean>
<bean class="com.fankf.spring.PersonExt" name="person,person1" init-method="myInit" destroy-method="myDestory" parent="p">
<property name="name" value="zhangsan"/>
</bean>
其中 parent="p" 指向了Person对象。进入方法查看源码:
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
return getMergedBeanDefinition(beanName, bd, null);
}
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
// Check with full lock now in order to enforce the same merged instance.
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
if (mbd == null) {
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
mbd = new RootBeanDefinition(bd);
}
}
else {
// Child bean definition: needs to be merged with parent.
BeanDefinition pbd;
try {
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without an AbstractBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
mbd = new RootBeanDefinition(pbd);
mbd.overrideFrom(bd);
}
// Set default singleton scope, if not configured before.
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
}
// A bean contained in a non-singleton bean cannot be a singleton itself.
// Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original inner bean
// definition will not have inherited the merged outer bean's singleton status.
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// Cache the merged bean definition for the time being
// (it might still get re-merged later on in order to pick up metadata changes)
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
return mbd;
}
}
获取bean语句修改成 :
PersonExt person = (PersonExt) context.getBean("person");
这里 getMergedLocalBeanDefinition(String beanName) 作用获取beanName 对应Bean实例,getMergedBeanDefinition(String beanName, BeanDefinition bd) 只做跳转使用,具体查看 getMergedBeanDefinition( String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd) 方法:
- containingBd == null 必定为 true ,从 mergedBeanDefinitions.get(beanName) 获取 beanDefination,此处也刚开始执行必定为空。
- 如果不存在parent='p' 那么就执行 mbd = new RootBeanDefinition(bd); 直接返回。
- 这里存在那么就 transformedBeanName(bd.getParentName()) 获取p,beanName.equals(parentBeanName) 则判断 "person".equals("p") 返回false,从而获取 p 别买对应的实例,其实就是对parent对应的Person类进行加载。
- mbd = new RootBeanDefinition(pbd) 从而对Person类进行GenericBeanDefination 转换成RootBeanDefination, mbd.overrideFrom(bd) 这里使用子类的方法覆盖同名的父类方法 。 这个才是主要的。对比原GenericBeanDefination内容还要多,多的内容是父类的未重写的属性和方法。
2.4、检测是否是抽象
checkMergedBeanDefinition 检测是否是抽象类,如果是直接报错。
protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
throws BeanDefinitionStoreException {
if (mbd.isAbstract()) {
throw new BeanIsAbstractException(beanName);
}
}
2.5、处理依赖的bean
获取所有依赖的bean,对依赖的bean进行注册 registerDependentBean 和 获取 getBean 。
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
2.6、判断是否是单例
单例情况下创建bean实例,这里 getObjectForBeanInstance 和 2.3 的内容是相同的。 而getSingleton 是获取bean,在此之前进行了createBean的过程。这里内容比较多,下篇讲解。
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
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;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
2.7、判断是否是原型
如果是原型模式,getObjectForBeanInstance 仍然是相同的。 不同在于在createBean 之前分别执行了beforePrototypeCreation 和 之后 afterPrototypeCreation 操作,都是对循环依赖的处理。
if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
2.8、非单例和原型的作用域统一处理
其他的作用域,先获取作用域,然后进行的操作和原型模式类似。最后 getObjectForBeanInstance 获取实例bean,之前进行的 createBean 前后分别处理循环依赖问题。
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
2.9、对获取bean的类型和需要的类型进行校验
这里主要是 getTypeConverter().convertIfNecessary(bean, requiredType); 这一句,我们这里没有对 requiredType 传值,所以就不仔细看了,有兴趣可以往里看,还是比较简单的。
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
3、总结
以上不是完全按照上面文章的顺序进行的讲解,有几个比较简单的就没有提到。其他三种实例化的情况因为内容比较多,就放到下篇再讲解,也是希望看到文章的朋友有新收获!
加油!共勉!