5.3 从bean的实例中获取对象
在getBean方法中,getObjectForBeanInstance是个高频率使用的方法,无论是从缓存中获得bean还是根据不同的scope策略加载bean。总之,我们得到bean的实例后要做的第一步就是调用这个方法来检测一下正确性,其实就是用于检测当前bean是否是FactoryBean类型的bean,如果是,那么需要调用该bean对应的FactoryBean实例中的getObject()作为返回值。
无论是从缓存中获取到的bean还是通过不同的scope策略加载的bean都只是最原始的bean状态,并不一定是我们最终想要的bean。举个例子,假如我们需要对工厂bean进行处理,那么这里得到的其实是工厂bean的初始状态,但是我们真正需要的是工厂bean中定义的factory-method方法中返回的bean,而getObjectForBeanInstance方法就是完成这个工作的。
1 protected Object getObjectForBeanInstance(
2 Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
3
4 //如果指定的name是工厂相关(以&为前缀)且beanInstance又不是FactoryBean类型则验证不通过
5 if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
6 throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance. getClass());
7 }
8
9 //现在我们有了个bean的实例,这个实例可能会是正常的bean或者是FactoryBean
10 //如果是FactoryBean我们使用它创建实例,但是如果用户想要直接获取工厂实例而不是工厂的getObject方法对应的实例那么传入的name应该加入前缀&
11 if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils. IsFactory Dereference(name)) {
12 return beanInstance;
13 }
14
15 //加载FactoryBean
16 Object object = null;
17 if (mbd == null) {
18 //尝试从缓存中加载bean
19 object = getCachedObjectForFactoryBean(beanName);
20 }
21 if (object == null) {
22 //到这里已经明确知道beanInstance一定是FactoryBean类型
23 FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
24 //containsBeanDefinition检测beanDefinitionMap中也就是在所有已经加载的类中检测是否定义beanName
25 if (mbd == null && containsBeanDefinition(beanName)) {
26 //将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition,如果指定BeanName是子Bean的话同时会合并父类的相关属性
27 mbd = getMergedLocalBeanDefinition(beanName);
28 }
29 //是否是用户定义的而不是应用程序本身定义的
30 boolean synthetic = (mbd != null && mbd.isSynthetic());
31 object = getObjectFromFactoryBean(factory, beanName, !synthetic);
32 }
33 return object;
34 }
从上面的代码来看,其实这个方法并没有什么重要的信息,大多是些辅助代码以及一些功能性的判断,而真正的核心代码却委托给了getObjectFromFactoryBean,我们来看看getObjectForBeanInstance中的所做的工作。
(1)对FactoryBean正确性的验证。
(2)对非FactoryBean不做任何处理。
(3)对bean进行转换。
(4)将从Factory中解析bean的工作委托给getObjectFromFactoryBean。
1 protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {
2 //如果是单例模式
3 if (factory.isSingleton() && containsSingleton(beanName)) {
4 synchronized (getSingletonMutex()) {
5 Object object = this.factoryBeanObjectCache.get(beanName);
6 if (object == null) {
7 object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
8 this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
9 }
10 return (object != NULL_OBJECT ? object : null);
11 }
12 }
13 else {
14 return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
15 }
16 }
很遗憾,在这个代码中我们还是没有看到想要看到的代码,在这个方法里只做了一件事情,就是返回的bean如果是单例的,那就必须要保证全局唯一,同时,也因为是单例的,所以不必重复创建,可以使用缓存来提高性能,也就是说已经加载过就要记录下来以便于下次复用,否则的话就直接获取了。
在doGetObjectFromFactoryBean方法中我们终于看到了我们想要看到的方法,也就是object = factory.getObject(),是的,就是这句代码,我们的历程犹如剥洋葱一样,一层一层的直到最内部的代码实现,虽然很简单。
1 private Object doGetObjectFromFactoryBean(
2 final FactoryBean factory, final String beanName, final boolean shouldPostProcess)
3 throws BeanCreationException {
4
5 Object object;
6 try {
7 //需要权限验证
8 if (System.getSecurityManager() != null) {
9 AccessControlContext acc = getAccessControlContext();
10 try {
11 object = AccessController.doPrivileged(new PrivilegedExceptionAction< Object>() {
12 public Object run() throws Exception {
13 return factory.getObject();
14 }
15 }, acc);
16 }
17 catch (PrivilegedActionException pae) {
18 throw pae.getException();
19 }
20 }
21 else {
22 //直接调用getObject方法
23 object = factory.getObject();
24 }
25 }
26 catch (FactoryBeanNotInitializedException ex) {
27 throw new BeanCurrentlyInCreationException(beanName, ex.toString());
28 }
29 catch (Throwable ex) {
30 throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
31 }
32 if (object == null && isSingletonCurrentlyInCreation(beanName)) {
33 throw new BeanCurrentlyInCreationException(
34 beanName, "FactoryBean which is currently in creation returned null from getObject");
35 }
36
37 if (object != null && shouldPostProcess) {
38 try {
39 //调用ObjectFactory的后处理器
40 object = postProcessObjectFromFactoryBean(object, beanName);
41 }
42 catch (Throwable ex) {
43 throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);
44 }
45 }
46
47 return object;
48 }
上面我们已经讲述了FactoryBean的调用方法,如果bean声明为FactoryBean类型,则当提取bean时提取的并不是FactoryBean,而是FactoryBean中对应的getObject方法返回的bean,而doGetObjectFromFactoryBean正是实现这个功能的。但是,我们看到在上面的方法中除了调用object = factory.getObject()得到我们想要的结果后并没有直接返回,而是接下来又做了些后处理的操作,这个又是做什么用的呢?于是我们跟踪进入AbstractAutowireCapableBeanFactory类的postProcessObjectFromFactoryBean方法:
1 protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
2 return applyBeanPostProcessorsAfterInitialization(object, beanName);
3 }
4 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
5 throws BeansException {
6
7 Object result = existingBean;
8 for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
9 result = beanProcessor.postProcessAfterInitialization(result, beanName);
10 if (result == null) {
11 return result;
12 }
13 }
14 return result;
15 }
对于后处理器的使用我们还未过多接触,后续章节会使用大量篇幅介绍,这里,我们只需了解在Spring获取bean的规则中有这样一条:尽可能保证所有bean初始化后都会调用注册的BeanPostProcessor的postProcessAfterInitialization方法进行处理,在实际开发过程中大可以针对此特性设计自己的业务逻辑。
来源:https://www.cnblogs.com/mjorcen/p/3583015.html