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方法进行处理,在实际开发过程中大可以针对此特性设计自己的业务逻辑。