从Bean的实例中获取对象
在getBean的方法中,getObjectForBeanInstance是使用频率很高的方法。我们得到bean的之后要做的第一步就是来检测一下正确性,其实就是用于检测当前bean是不是FactoryBean类型的Bean,如果是,那么需要调用该bean对应的FactoryBean实例中的getObject作为返回值。
无论是从缓存中还是通过不同的scope策略加载的bean都只是原始的bean状态,并不一定是我们最终想要的bean。举个例子,加入我们需要对工厂bean进行处理,那么这里得到的其实就是工厂bean的初始状态,但是我们真正想要的是工厂bean中定义的Factory-method方法返回的bean实例,而getObjectForBeanInstance方法就是完成这个工作的。
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
// 如果指定的bean是工厂相关(以&作为前缀),且beanInstance又不是FactoryBean类型,则验证不通过
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
// 现在我们有了bean实例,这个实例可能是一个正常的bean或者是FactoryBean。
// 如果是FactoryBean,我们使用它来创建一个bean实例,但是如果用户想要直接获取工厂实例而不是工厂的getObject方法
// 对应的实例那么传入的name应该加前缀&
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
// 加载FactoryBean
Object object = null;
if (mbd == null) {
// 如果父标签不存在,先从缓存取
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
// 到这里明确知道beanInstance一定是FactoryBean
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
// containsBeanDefinition检测beanDefinitionMap中也就是在所有已经加载的类中检测是否定义了beanName。
if (mbd == null && containsBeanDefinition(beanName)) {
// 将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition,
// 如果指定BeanName是子Bean的话,同时合并父类的相关属性
mbd = getMergedLocalBeanDefinition(beanName);
}
// 是否用户定义的而非程序本身定义的
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
从代码看,这个方法没有什么实质内容,都是一些辅助性的功能判断,真正核心的代码委托给了getObjectFromFactoryBean。我们看一下getObjectForBeanInstance的处理过程:
- 对FactoryBean的正确性做出验证
- 对非FactoryBean不做处理
- 对bean进行转换
- 将从Factory中解析bean的工作委托给getObjectFromFactoryBean。我们看一下getObjectFromFactoryBean的代码。
这个方法getObjectFromFactoryBean也没有什么,就是判断bean是不是单例,如果是保证全局的唯一性,做缓存。当然创建的时候都是调用doGetObjectFromFactoryBean方法。
是的在这个doGetObjectFromFactoryBean方法中最终还是使用FactoryBean#getObject方法。
调用getObjectFromFactoryBean方法之后它没有直接返回,而是做了一些后续处理。
我们进入AbstractAutowireCapableBeanFactory#postProcessObjectFromFactoryBean方法。
对于这个方法的实现他是与注解相关,这里不再多说,看到再说吧!这里我们只需要了解在Spring获取bean的规则中有这样一条:尽可能保证所有bean初始化后都会调用注册的BeanPostProcessor的postProcessAfterInitialization方法进行处理,在实际开发中大可以针对此特性设计自己的业务逻辑。