zoukankan      html  css  js  c++  java
  • 转:Spring FactoryBean源码浅析

    http://blog.csdn.net/java2000_wl/article/details/7410714

    在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的生产 修饰做了很好的封装。

  • 相关阅读:
    网上零售是国内品牌开拓海外市场的最佳途径
    一个都不能少,海外B2C实战攻略全解
    我想和你一起浅浅淡淡的生活
    中国十大电子商务网站排名
    外贸B2C必读:外贸B2C入行指南(一)
    外贸B2C必读:外贸B2C入行指南(二)
    09年美国最热门的100个B2C网站,他们是怎么成功的?
    几个jsp模块
    【Quartz】【程序目录结构】/DetectNonWorkingDay/src/main/java/com/apple/sqm/dnwd/detect/delta/Detect.java
    Servlet 工作原理解析
  • 原文地址:https://www.cnblogs.com/lanhzbupt/p/3888939.html
Copyright © 2011-2022 走看看