`

在Spring BeanFactory容器中管理两种bean

阅读更多

在Spring BeanFactory容器中管理两种bean  

1.标准Java Bean  

2,另一种是工厂Bean,   即实现了FactoryBean接口的bean  它不是一个简单的Bean 而是一个生产或修饰对象生成的工厂Bean

在向Spring容器获得bean时  对于标准的java Bean  返回的是类自身的实例 

而FactoryBean 其返回的对象不一定是自身类的一个实例,返回的是该工厂Bean的getObject方法所返回的对象

一个简单的例子

  1. public class SayHelloFactoryBeanImpl implements FactoryBean {  
  2.   
  3.     /** 
  4.      * 返回该工厂生成的bean 
  5.      */  
  6.     public Object getObject() throws Exception {  
  7.         return new ChinaSayHelloServiceImpl();  
  8.     }  
  9.   
  10.     /** 
  11.      * getObject返回对象对应的Class 
  12.      */  
  13.     public Class getObjectType() {  
  14.         return ChinaSayHelloServiceImpl.class;  
  15.     }  
  16.       
  17.     /** 
  18.      * getObject返回的对象 是否是一个单例 
  19.      */  
  20.     public boolean isSingleton() {  
  21.         return false;  
  22.     }  
  23. }  
  1. 配置文件  
  2. <bean id="sayHelloFactoryBean" class="com.xx.service.impl.SayHelloFactoryBeanImpl" />  
  1. ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"classpath:applicationContext-server.xml"}, true);  
  2. //bean的 getObject方法 返回的对象   
  3. Object object = context.getBean("sayHelloFactoryBean");  
  4. System.out.println(object);  

控制台输出

com.xx.service.impl.ChinaSayHelloServiceImpl@1f66cff

容器返回的是 bean getObject方法返回对象  而不是SayHelloFactoryBeanImpl自身的实例 当然可以用“&”符号转义 获得FactoryBean的自身实例

  1. ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"classpath:applicationContext-server.xml"}, true);  
  2.         //可以用转义符"&"来获得FactoryBean本身实例          
  3.         System.out.println(context.getBean("&sayHelloFactoryBean"));  

控制台输出

com.xx.service.impl.SayHelloFactoryBeanImpl@75e4fc

下面看看FactoryBean是怎么实现的

Spring  FactoryBean接口定义

  1. public interface FactoryBean {  
  2.   
  3.     Object getObject() throws Exception;  
  4.   
  5.     Class getObjectType();  
  6.   
  7.     boolean isSingleton();  
  8. }  

bean的实例化 是在AbstractBeanFactory getBean方法发生的

  1. public Object getBean(String name, Class requiredType, Object[] args) throws BeansException {  
  2.         return doGetBean(name, requiredType, args, false);  
  3.     }  
  1. protected Object doGetBean(final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {  
  2.         // bean name处理  如果是以"&"开头  截取掉     
  3.         final String beanName = transformedBeanName(name);  
  4.         Object bean = null;  
  5.         //单例的bean 只实例化一次  第一次实例化后会放到一个Map中 即singletonObjects map集合中  下次使用的时候直接拿   
  6.         Object sharedInstance = getSingleton(beanName);  
  7.         if (sharedInstance != null && args == null) {  
  8.             // FactoryBean 相关处理 在此方法发生   
  9.             //name 调用getBean时传入的参数    
  10.             //beanName 截取"&"后的name   
  11.             bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  
  12.         }  
  13.   
  14.         else {  
  15.             ...略  
  16.         }  
  17.         return bean;  
  18. }  
  1. protected Object getObjectForBeanInstance(  
  2.         Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {  
  3.     // 如果不是FactoryBean的相关调用 结束处理   
  4.     //isFactoryDereference 方法判断name 是不是以"&"开始  如果以"&"开始 返回true   
  5.     if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {  
  6.         throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());  
  7.     }  
  8.     if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {  
  9.         return beanInstance;  
  10.     }  
  11.     Object object = null;  
  12.     //bean的定义为null   
  13.     if (mbd == null) {  
  14.         //缓存集合factoryBeanObjectCache中包含  当前bean getObject方法返回的实例  不需要在调用 直接返回   
  15.         object = getCachedObjectForFactoryBean(beanName);  
  16.     }  
  17.     if (object == null) {  
  18.         FactoryBean factory = (FactoryBean) beanInstance;  
  19.         //containsBeanDefinition方法->  bean的定义map beanDefinitionMap集合中 是否包含该bean的定义   
  20.         if (mbd == null && containsBeanDefinition(beanName)) {  
  21.             mbd = getMergedLocalBeanDefinition(beanName);  
  22.         }  
  23.         boolean synthetic = (mbd != null && mbd.isSynthetic());  
  24.         // FactoryBean getObject触发   并缓存到factoryBeanObjectCache集合中   
  25.         object = getObjectFromFactoryBean(factory, beanName, !synthetic);  
  26.     }  
  27.     return object;  
  28. }  
  1. protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {  
  2.     //当前的factoryBean是否单例  并且  缓存singletonObjects‘Map中包含FactoryBean的自身实例   
  3.     if (factory.isSingleton() && containsSingleton(beanName)) {  
  4.         synchronized (getSingletonMutex()) {  
  5.             // factoryBeanObjectCache 缓存的是 getObject返回的对象   
  6.             Object object = this.factoryBeanObjectCache.get(beanName);  
  7.             if (object == null) {  
  8.                 //getObject方法调用   
  9.                 object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);  
  10.                 //缓存 getObject方法返回的实例对象   
  11.                 this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));  
  12.             }  
  13.             return (object != NULL_OBJECT ? object : null);  
  14.         }  
  15.     }  
  16.     else {  
  17.         //getObject方法调用   
  18.         return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);  
  19.     }  
  20. }  
  1. private Object doGetObjectFromFactoryBean(  
  2.         final FactoryBean factory, final String beanName, final boolean shouldPostProcess)  
  3.         throws BeanCreationException {  
  4.     AccessControlContext acc = AccessController.getContext();  
  5.     return AccessController.doPrivileged(new PrivilegedAction() {  
  6.         public Object run() {  
  7.             Object object;  
  8.   
  9.             try {  
  10.                 // getObject方法调用   
  11.                 object = factory.getObject();  
  12.             }  
  13.             catch (FactoryBeanNotInitializedException ex) {  
  14.                 throw new BeanCurrentlyInCreationException(beanName, ex.toString());  
  15.             }  
  16.             catch (Throwable ex) {  
  17.                 throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);  
  18.             }  
  19.             if (object == null && isSingletonCurrentlyInCreation(beanName)) {  
  20.                 throw new BeanCurrentlyInCreationException(  
  21.                         beanName, "FactoryBean which is currently in creation returned null from getObject");  
  22.             }  
  23.   
  24.             if (object != null && shouldPostProcess) {  
  25.                 try {  
  26.                     object = postProcessObjectFromFactoryBean(object, beanName);  
  27.                 }  
  28.                 catch (Throwable ex) {  
  29.                     throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);  
  30.                 }  
  31.             }  
  32.   
  33.             return object;  
  34.         }  
  35.     }, acc);  
  36. }  

当一个受Spring容器管理的bean  如果实现了FactoryBean接口  在bean实例化(getBean)阶段  Spring会调用该bean的getObejct方法 返回的不一定是自身的实例

Spring 框架中有很多FactoryBean   例如RmiProxyFactoryBean, SqlMapClientFactoryBean. LocalSessionFactoryBean等都是通过FactoryBean getObject方法驱动起来的.对bean的生产 修饰做了很好的封装。

分享到:
评论

相关推荐

    开源框架 Spring Gossip

    管理 Bean 从第一个 Spring 应用程式开始,逐步了解何谓依赖注入,以及如何使用 Spring 的容器功能来管理 Bean,了解 Bean 在 Spring 容器中的生命周期。 第一个 Spring 程式 BeanFactory、 ...

    高级开发spring面试题和答案.pdf

    spring 三种注入(就是从spring容器中将bean放入对象属性值中) Spring下描述依赖关系@Resource, @Autowired和@Inject的区别与联系 Spring中BeanFactory和ApplicationContext的区别 谈谈Spring IOC的理解,原理与...

    Spring面试题

    spring以动态灵活的方式来管理对象 , 注入的两种方式,设置注入和构造注入。 设置注入的优点:直观,自然 构造注入的优点:可以在构造器中决定依赖关系的顺序。 什么是AOP? 面向切面编程(AOP)完善spring的...

    java查看sun包源码-learning-spring:Spring框架讲解

    Spring提供了两种类型的IOC容器实现 BeanFactory:IOC容器的基本实现,在调用getBean()方法时才会实例化对象 ApplicationContext:提供了更多的高级特性,在加载配置文件后就会实例化对象。是BeanFactory的子接口 ...

    第24次课-1 Spring与Hibernate的整合

    Spring配置管理SessionFactory与数据库的连接,在实际的应用中,数据源会采用依赖注入的方式,传递给SessionFactory。 见beans-config_sh.xml 24.3 Spring对Hibernate的简化 24.3.1 概述 Hibernate的持久层访问步骤...

    海创软件组-Spring 核心之IoC(一)

    Spring IoC容器的两个接口 依赖注入的类型 Bean的配置 …IOC:控制反转依赖注入。它使程序组件或类之间尽量形成一种松耦合的结构,开发者在使用类的实列之前,需要先创建对象的实列。而IoC是将创建实列的任务交给了...

    J2EE应用开发详解

    247 14.6 小结 248 第15章 Spring框架 249 15.1 Spring 2.0的体系结构 249 15.2 Ioc容器 250 15.2.1 BeanFactory 250 15.2.2 ApplicationContext 252 15.2.3 Beans的生命周期过程 253 15.2.4 Beans的进阶管理 ...

    JAVA核心知识点整理(有效)

    1. 目录 1. 2. 目录 .........................................................................................................................................................1 JVM ........................

Global site tag (gtag.js) - Google Analytics