Spring中的FactoryBean

1.概述 
         Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean,即FactoryBean,这两种Bean都被容器管理,但工厂Bean跟普通Bean不同,其返回的对象不是指定类的一个实例,其返回的是该FactoryBean的getObject方法所返回的对象。在Spring框架内部,有很多地方有FactoryBean的实现类,它们在很多应用如(Spring的AOP、ORM、事务管理)及与其它第三框架(ehCache)集成时都有体现,下面简单分析FactoryBean的用法。 

2.实例 
以下SimpleFactoryBean类实现了FactoryBean接口中的三个方法。 并将该类配置在XML中。 

Java代码   收藏代码
  1. public class SimpleFactoryBean implements FactoryBean {  
  2.         private boolean flag;  
  3.       
  4.         public Object getObject() throws Exception {  
  5.             if (flag) {  
  6.                 return new Date();  
  7.             }  
  8.             return new String("false");  
  9.         }  
  10.       
  11.         @SuppressWarnings("unchecked")  
  12.         public Class getObjectType() {  
  13.             return flag ? Date.class : String.class;  
  14.         }  
  15.       
  16.         public boolean isSingleton() {  
  17.             return false;  
  18.         }  
  19.       
  20.         public void setFlag(boolean flag) {  
  21.             this.flag = flag;  
  22.         }  
  23.     }  
  24.       
  25.     <bean id="factoryBeanOne" class="com.study.demo.factorybean.SimpleFactoryBean" >  
  26.         <property name="flag">  
  27.             <value>true</value>  
  28.         </property>  
  29.     </bean>  
  30.       
  31.     <bean id="factoryBeanTwo" class="com.study.demo.factorybean.SimpleFactoryBean" >  
  32.         <property name="flag">  
  33.             <value>false</value>  
  34.         </property>  
  35.     </bean>  
  36.       
  37.     public class MainTest {  
  38.         public static void main(String[] args) {  
  39.             Resource res = new ClassPathResource("bean.xml");  
  40.             BeanFactory factory = new XmlBeanFactory(res);  
  41.             System.out.println(factory.getBean("factoryBeanOne").getClass());  
  42.             System.out.println(factory.getBean("factoryBeanTwo").getClass());  
  43.         }  
  44.     }  


通过简单的测试可知,该类输出如下: 
class java.util.Date 
class java.lang.String 
也就是说,容器通过getBean方法返回的不是FactoryBean本身,而是FactoryBean实现类中getObject()方法所返回的对象。 

3.FactoryBean的扩展应用  
以Spring集成 ehcache 为例,看下org.springframework.cache.ehcache.EhCacheManagerFactoryBean类与org.springframework.cache.ehcache.EhCacheFactoryBean类。EhCacheManagerFactoryBean类中的getObject()和getObjectType() 方法返回的如下: 
Java代码   收藏代码
  1. public Object getObject() {  
  2.             return this.cacheManager;  
  3.         }  
  4.       
  5.     public Class getObjectType() {  
  6.             return (this.cacheManager != null ? this.cacheManager.getClass() : CacheManager.class);  
  7.         }  


EhCacheFactoryBean类中的getObject()和getObjectType() 方法返回的如下: 
Java代码   收藏代码
  1. public Object getObject() {  
  2.             return this.cache;  
  3.         }  
  4.       
  5.         public Class getObjectType() {  
  6.             return (this.cache != null ? this.cache.getClass() : Ehcache.class);  
  7.         }  

有了这两个FactoryBean,在Spring容器中使用ehcache就变得很简单了。配置如下: 
Java代码   收藏代码
  1. <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">    
  2.               <property name="configLocation">    
  3.               <value>classpath:ehcache.xml</value>    
  4.               </property>    
  5.         </bean>    
  6.       
  7.         <bean id="levelOneCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">    
  8.               <property name="cacheManager">    
  9.                     <ref local="cacheManager" />    
  10.               </property>    
  11.               <property name="cacheName">    
  12.                     <value>levelOneCache</value>    
  13.               </property>    
  14.         </bean>  

应用代码如下: 
Java代码   收藏代码
  1. public class MainTest {  
  2.             public static void main(String[] args) {  
  3.                 Resource res = new ClassPathResource("bean.xml");  
  4.                 BeanFactory factory = new XmlBeanFactory(res);  
  5.                 //取到CacheManager类的实例   
  6.                 CacheManager cacheManager = (CacheManager) factory  
  7.                         .getBean("cacheManager");  
  8.                 //取到Cache类的实例   
  9.                 Cache levelOneCache = cacheManager.getCache("levelOneCache");  
  10.             }  
  11.         }  
  12.           

还有一篇文章


Spring  FactoryBean 是创建 复杂的bean,一般的bean 直接用xml配置即可,如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,用xml配置比较困难,这时可以考虑用FactoryBean

例子如下:

1:创建一个Car类(是为了简便)一般不能直接给出Car类,如果是这样直接注入就可以或者Car对象了,这里只是为了简便。

[java]  view plain copy
  1. <span style="font-size:10px;">package com.myapp.core.factorybean;  
  2.   
  3. public class Car {  
  4.   private  String  make;  
  5.   private  int year;  
  6.     public String getMake() {  
  7.         return make;  
  8.     }  
  9.     public void setMake(String make) {  
  10.         this.make = make;  
  11.     }  
  12.     public int getYear() {  
  13.         return year;  
  14.     }  
  15.     public void setYear(int year) {  
  16.         this.year = year;  
  17.     }  
  18.         
  19. }</span><span style="font-size:24px;">  
  20. </span>  

2:一个FactoryBean的实现拥有创建car

[java]  view plain copy
  1. package com.myapp.core.factorybean;  
  2.   
  3. import org.springframework.beans.factory.FactoryBean;  
  4.   
  5. public class MyCarFactoryBean  implements FactoryBean<Car>{  
  6.       
  7.     private String  make;  
  8.       
  9.     private  int  year;  
  10.   
  11.     public void setMake(String make) {  
  12.         this.make = make;  
  13.     }  
  14.   
  15.     public void setYear(int year) {  
  16.         this.year = year;  
  17.     }  
  18.   
  19.     @Override  
  20.     public Car getObject() throws Exception {  
  21.         // TODO Auto-generated method stub  
  22.           
  23.         //Here  is a complex  car  object  created  
  24.          // wouldn't be a very useful FactoryBean  
  25.         // if we could simply instantiate the object!  
  26.         Car  car  = new  Car();  
  27.           
  28.         if(year != 0){  
  29.            car.setYear(this.year);  
  30.         }  
  31.           
  32.         if("make".equals(make)){  
  33.             car.setMake("we are making  bla bla  bla");  
  34.         }else{  
  35.             car.setMake(this.make);  
  36.         }  
  37.           
  38.         return  car;  
  39.     }  
  40.   
  41.     @Override  
  42.     public Class<?> getObjectType() {  
  43.         // TODO Auto-generated method stub  
  44.         return Car.class;  
  45.     }  
  46.   
  47.     @Override  
  48.     public boolean isSingleton() {  
  49.         // TODO Auto-generated method stub  
  50.         return false;  
  51.     }  
  52.   
  53. }  

以上中创建car太简单了,如果太简单就没有必要用FactoryBean创建了,可以写的复杂些。


3:Person 引用一个car


[java]  view plain copy
  1. package com.myapp.core.factorybean;  
  2.   
  3. public class Person {  
  4.    
  5.     private  Car  car;  
  6.   
  7.     public Car getCar() {  
  8.         return car;  
  9.     }  
  10.   
  11.     public void setCar(Car car) {  
  12.         this.car = car;  
  13.     }  
  14.       
  15.     public  String  toString(){  
  16.           
  17.         return  car.getMake()+"::::"+car.getYear();  
  18.     }  
  19. }  

4:配置引用xml格式:


[html]  view plain copy
  1. <bean id="car" class="com.myapp.core.factorybean.MyCarFactoryBean">  
  2.    <property name="make" value="makeing car"/>  
  3.    <property name="year"  value="123"/>  
  4. </bean>  
  5.   
  6. <bean id="person" class="com.myapp.core.factorybean.Person">  
  7.   
  8. <property name="car" ref="car"/>  
  9.   
  10. </bean>  

5:编写测试类测试:

[java]  view plain copy
  1. package com.myapp.core.factorybean;  
  2.   
  3. import org.springframework.context.ApplicationContext;  
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  5.   
  6. public class MainTest {  
  7.   public static void main(String[] args) {  
  8.       
  9.       ApplicationContext  context  = new  ClassPathXmlApplicationContext("resource/others.xml");  
  10.         
  11.  Person  person =   (Person)context.getBean("person");  
  12.         
  13.      // Car  car =   (Car)context.getBean("car");  
  14.         
  15.     //  System.out.println(car);  
  16.     System.out.println(person);  
  17. }  
  18. }  

测试结果 makeing car::::123
利用FactoryBean创建car成功
只是为了说明思想。因为这个接口太重要了。在Spring中有很多类实现了改接口over




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值