写在前面的话
源码层面解读spring中bean的循环依赖解决方案系列来到了最终章,
我们主要研究spring如何从bean的实例中获取对象。
从bean的实例中获取对象
在getBean的方法中,getObjectForBeanInstance是一个高频使用的方法,无论是从缓存中获取还是从不同的scope策略加载bean。
这个方法的主要作用就是检测当前bean是否是FactoryBean类型的bean,如果是,就需要条
用该bean队友的FactoryBean实例中的getObject()作为放回值。
这里抛出一个问题,我们从从缓存中获取还是从不同的scope策略加载获取到的bean,都只是原始的bean状态,
不一定是我们想要的bean。
比如,我们需要对工厂bean进行处理的时候,上面获取到的bean就只是初始状态,而我们其实需要的是工厂bean中定义的factory-method方法返回的bean,getObjectForBeanInstance方法就能完成这个工作。
getObjectForBeanInstance
/**
* Get the object for the given bean instance, either the bean
* instance itself or its created object in case of a FactoryBean.
* 获取给定bean实例的对象,对于FactoryBean,可以是bean实例本身,也可以是它创建的对象。
* @param beanInstance the shared bean instance
* @param name the name that may include factory dereference prefix
* @param beanName the canonical bean name
* @param mbd the merged bean definition
* @return the object to expose for the bean
*/
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.
// 如果指定的name是工程相关(以&为前缀)且beanInstance又不是FactoryBean类型则严重不通过
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, 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.
// 现在我们有了bean实例,它可以是一个普通的bean或FactoryBean。
// 如果它是一个FactoryBean,我们使用它来创建一个bean实例,除非
// 调用者实际上想要一个对工厂的引用,而不是工程的getObject方法队友的实例那么传入的neam应该加前缀&
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
//加载FactoryBean
Object object = null;
if (mbd == null) {
//尝试从缓存中加载bean
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;
}
getObjectForBeanInstance内部做了一下几件事:
1.对FactoryBean正确性进行验证。
2.非FactoryBean不做任何处理。
3.对bean进行转换
4.把从Factory解析bean的工作委托给getObjectFromFactoryBean方法
getObjectFromFactoryBean
/**
* Obtain an object to expose from the given FactoryBean.
* 获取要从给定的FactoryBean公开的对象。
* @param factory the FactoryBean instance
* @param beanName the name of the bean
* @param shouldPostProcess whether the bean is subject to post-processing
* @return the object obtained from the FactoryBean
* @throws BeanCreationException if FactoryBean object creation failed
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
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) {
// 获取对象从FactoryBean
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
// 如果在上面调用getObject()时没有放在那里,则只进行后处理和存储
// (例如,由于循环引用处理由自定义getBean调用触发)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
// 暂时返回非后期处理的对象,不存储它。
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)) {
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;
}
}
getObjectFromFactoryBean方法中只做了一件事情就是返回的bean如果是单例,
那就必须要保证全局唯一。
同时,也是因为是单例,索引不需要重复创建,可以使用缓存来提高性能,也就是说已经加载过就要记录下来以便下次服用,否则的话就直接获取了。
doGetObjectFromFactoryBean
在这个方法中就有了直接调用的getObject()方法。
object = factory.getObject();
/**
* Obtain an object to expose from the given FactoryBean.
* 获取要从给定的FactoryBean公开的对象。
* @param factory the FactoryBean instance
* @param beanName the name of the bean
* @return the object obtained from the FactoryBean
* @throws BeanCreationException if FactoryBean object creation failed
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
//需要权限验证
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//直接调用getObject方法
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
//不接受一个不完全的FactoryBean的空值
//许多FactoryBeans返回null
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}
至此我们讲述了整个从FactoryBean的调用方法, 就是如果bean声明为FactoryBean类型,则当提取bean时提取的并不是FactoryBean,而是FactoryBean中对应的getObject方法返回的bean,
方法实现就是doGetObjectFromFactoryBean。
接下来回到getObjectFromFactoryBean方法中,
有这样一段代码:
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
// 暂时返回非后期处理的对象,不存储它。
return object;
}
beforeSingletonCreation(beanName);
try {
//调用ObjectFactory的后处理器
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
里面提到postProcessObjectFromFactoryBean方法,在
//获取对象从FactoryBean
object = doGetObjectFromFactoryBean(factory, beanName);
得到我们想要的结果后,并没有直接返回,而是调用了后处理器操作postProcessObjectFromFactoryBean。
postProcessObjectFromFactoryBean
/**
* Post-process the given object that has been obtained from the FactoryBean.
* The resulting object will get exposed for bean references.
* <p>The default implementation simply returns the given object as-is.
* Subclasses may override this, for example, to apply post-processors.
* 对从FactoryBean获得的给定对象进行后处理。
* 结果对象将被公开给bean引用。
* <p>默认的实现简单地返回给定的对象。
* 子类可以覆盖这个,例如,应用后处理器。
* @param object the object obtained from the FactoryBean.
* @param beanName the name of the bean
* @return the object to expose
* @throws org.springframework.beans.BeansException if any post-processing failed
*/
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
return object;
}
这里提到postProcessObjectFromFactoryBean方法是留给子类覆盖的。
所以我们接着看子类AbstractAutowireCapableBeanFactory对postProcessObjectFromFactoryBean方法的覆写源码。
/**
* Applies the {@code postProcessAfterInitialization} callback of all
* registered BeanPostProcessors, giving them a chance to post-process the
* object obtained from FactoryBeans (for example, to auto-proxy them).
* 应用所有的{@code postProcessAfterInitialization}回调
* 注册了BeanPostProcessors,让他们有机会对
* 从FactoryBeans获取的对象(例如,自动代理它们)。
* @see #applyBeanPostProcessorsAfterInitialization
*/
@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
return applyBeanPostProcessorsAfterInitialization(object, beanName);
}
接着看applyBeanPostProcessorsAfterInitialization方法
@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;
}
可以看出就是会调用postProcessAfterInitialization方法,
Spring获取bean的一条规则:
尽可能保证所有bean初始化后都会调用注册的BeanPostProcessor的postProcessAfterInitialization方法进行处理。
这个postProcessAfterInitialization方法在
从源码层面解读spring中bean的循环依赖解决方案(3)
中的初始化bean中就有过介绍,目的是使用户可以根据自己的业务需求进行响应处理。
写在后面的话
这一篇我们介绍了如何从bean的实例中获取对象,也从源码出发解释了如何从bean中获取对象。
下一篇我们回归正题,进入到createBean方法中去找寻创建bean的最终真相。