5.3:从bean的实例中获取对象

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方法返回的beandoGetObjectFromFactoryBean正是实现这个功能的。但是,我们看到在上面的方法中除了调用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初始化后都会调用注册的BeanPostProcessorpostProcessAfterInitialization方法进行处理,在实际开发过程中大可以针对此特性设计自己的业务逻辑。

 

 

 

 

 

 

posted @ 2014-04-21 17:55  mjorcen  阅读(443)  评论(0编辑  收藏  举报