浅析Spring IoC源码(七)浅谈BeanFactory和FactoryBean

这一节我们就简单的介绍一下FactoryBean,知道这个接口的作用和意义,方便我们refresh()这个方法的理解

照旧,我们依旧先看源码,从源码中查看一下他的作用吧~

这次就不一句句翻译了(太多了),还是稍微大概的讲一下意思吧:FactoryBean是一个接口,任何一个Bean可以实现这个接口,那么这个bean将成为一个Factory,这个Factory将一些对象暴露出去,这些对象不一定是它们自己,返回的是一个Object对象,这个对象将通过getObject()暴露出去,并且支持单例和prototypes


这个接口有多重要?

看看这段:这个接口在spring自己的框架中被大篇幅的运用到,举例来说,AOP中link org.springframework.aop.framework.ProxyFactoryBean和org.springframework.jndi.JndiObjectFactoryBean


但是他在非底层代码建设之外并不常见~



好了,看了官方的注释,还是有点模糊的吧,不过我们可以再看看ProxyFactoryBean这个官方的代码,其实看名字,“代理”,这个接口可以用于代理,想想也是,“任何bean实现了BeanFactory都可以通过getObject()这个方法去返回一个Object类型的bean,这个就很重要了”


接下来,还是老规矩,我们举个例子,来具体说明这个接口的作用,我们也做一个Proxy,通过切换注入数据库的名字,切换给出的数据库操作,如果我们注入MySQL我们就可以操作数据到mysql,如果注入Redis我们可以操作数据到redis


首先定义一个数据库操作接口

DBOperation.Java

[java]  view plain  copy
  1. <span style="color:#000000;">package org.study.spring.factorybean;  
  2.   
  3. /** 
  4.  *  
  5.  * 数据库操作对象 
  6.  */  
  7. public interface DBOperation<T extends DBEntity> {  
  8.       
  9.     int save(T t);  
  10.       
  11.     int update(T t);  
  12.       
  13.     int delete(T t);  
  14.       
  15.     T select(Integer id);  
  16.       
  17.   
  18. }</span>  
DBEntity.java

[java]  view plain  copy
  1. <span style="color:#000000;">package org.study.spring.factorybean;  
  2.   
  3. /** 
  4.  *  
  5.  * 数据库保存对象 
  6.  * 
  7.  */  
  8. public class DBEntity {  
  9.       
  10.     private Integer id;  
  11.   
  12.     public Integer getId() {  
  13.         return id;  
  14.     }  
  15.   
  16.     public void setId(Integer id) {  
  17.         this.id = id;  
  18.     }  
  19.       
  20.   
  21. }</span>  
MysqlDB.java

[java]  view plain  copy
  1. <span style="color:#000000;">package org.study.spring.factorybean;  
  2.   
  3. /** 
  4.  * mysql数据操作 
  5.  * @author 
  6.  * 
  7.  */  
  8. public class MysqlDB implements DBOperation<MysqlDBEntity>{  
  9.   
  10.     public int save(MysqlDBEntity t) {  
  11.         System.out.println("save object to mysql");  
  12.         return 1;  
  13.     }  
  14.   
  15.     public int update(MysqlDBEntity t) {  
  16.         System.out.println("update object to mysql");  
  17.         return 0;  
  18.     }  
  19.   
  20.     public int delete(MysqlDBEntity t) {  
  21.         System.out.println("delete object from mysql");  
  22.         return 0;  
  23.     }  
  24.   
  25.     public MysqlDBEntity select(Integer id) {  
  26.         return new MysqlDBEntity();  
  27.     }  
  28. }</span>   
RedisDB.java

[java]  view plain  copy
  1. <span style="color:#000000;">package org.study.spring.factorybean;  
  2.   
  3.   
  4. /** 
  5.  *  
  6.  * redis数据库操作 
  7.  * 
  8.  */  
  9. public class RedisDB implements DBOperation<RedisDBEntity>{  
  10.   
  11.     public int save(RedisDBEntity t) {  
  12.         System.out.println("save this object"+t.getJsonStr());  
  13.         return 1;  
  14.     }  
  15.   
  16.     public int update(RedisDBEntity t) {  
  17.         System.out.println("update this object"+t.getJsonStr());  
  18.         return 0;  
  19.     }  
  20.   
  21.     public int delete(RedisDBEntity t) {  
  22.         System.out.println("delete this object"+t.getJsonStr());  
  23.         return 1;  
  24.     }  
  25.   
  26.     public RedisDBEntity select(Integer id) {  
  27.         System.out.println("select this object by id "+id);  
  28.         return new RedisDBEntity();  
  29.     }  
  30.       
  31.   
  32. }</span>  
MysqlDBEntity.java

[java]  view plain  copy
  1. <span style="color:#000000;">package org.study.spring.factorybean;  
  2.   
  3.   
  4. public class MysqlDBEntity extends DBEntity{  
  5.       
  6.     private String attribute;  
  7.   
  8.     public String getAttribute() {  
  9.         return attribute;  
  10.     }  
  11.   
  12.     public void setAttribute(String attribute) {  
  13.         this.attribute = attribute;  
  14.     }  
  15.   
  16. }</span>  
RedisDBEntity.java

[java]  view plain  copy
  1. <span style="color:#000000;">package org.study.spring.factorybean;  
  2.   
  3. public class RedisDBEntity extends DBEntity {  
  4.       
  5.     private String jsonStr;  
  6.   
  7.     public String getJsonStr() {  
  8.         return jsonStr;  
  9.     }  
  10.   
  11.     public void setJsonStr(String jsonStr) {  
  12.         this.jsonStr = jsonStr;  
  13.     }  
  14.       
  15.   
  16. }</span>  
ProxyDBObject.java

[java]  view plain  copy
  1. <span style="color:#000000;">package org.study.spring.factorybean;  
  2.   
  3. import org.springframework.beans.factory.FactoryBean;  
  4.   
  5.   
  6. /** 
  7.  *  
  8.  * DB代理,根据用户注入数据库的名称,自动返回对应的数据库操作给用户 
  9.  * 
  10.  */  
  11. public class ProxyDBObject implements FactoryBean<Object>{  
  12.       
  13.     private String currentDB;  
  14.       
  15.   
  16.     public String getCurrentDB() {  
  17.         return currentDB;  
  18.     }  
  19.   
  20.     public void setCurrentDB(String currentDB) {  
  21.         this.currentDB = currentDB;  
  22.     }  
  23.   
  24.     public Object getObject() throws Exception {  
  25.         if("mysql".equals(currentDB)){  
  26.             return new MysqlDB();  
  27.         }  
  28.         return new RedisDB();  
  29.     }  
  30.   
  31.     public Class<?> getObjectType() {  
  32.         if("mysql".equals(currentDB)){  
  33.             return MysqlDB.class;  
  34.         }  
  35.         return RedisDB.class;  
  36.     }  
  37.   
  38.     public boolean isSingleton() {  
  39.         return false;  
  40.     }  
  41.   
  42.        
  43.        
  44.   
  45. }</span>  

factory-bean.xml

[html]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
  4.     xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"  
  5.     xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"  
  6.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  
  7.         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd  
  8.         http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd  
  9.         http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd  
  10.         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">  
  11.    
  12.       
  13.             
  14.          <bean id="proxyDB" class="org.study.spring.factorybean.ProxyDBObject">  
  15.            <property name="currentDB" value="mysql"/>  
  16.          </bean>  
  17.   
  18. </beans>  

ProxyDBObjectTest.java

[java]  view plain  copy
  1. package org.study.spring.factorybean;  
  2.   
  3. import org.junit.Test;  
  4. import org.springframework.context.ApplicationContext;  
  5. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  6.   
  7. public class ProxyDBObjectTest{  
  8.       
  9.       
  10.     @Test  
  11.     public void test2() throws Exception{  
  12.          ApplicationContext applicationContext = new ClassPathXmlApplicationContext("factory-bean.xml");  
  13.          DBOperation dBoperation =  applicationContext.getBean("proxyDB",DBOperation.class);  
  14.          MysqlDBEntity dbEntity = new MysqlDBEntity();  
  15.          dBoperation.save(dbEntity);  
  16.     }  
  17.   
  18. }  

当配置currentDB为“mysql”时,运行结果是:


切换到redis会报错,因为我们保存的对象是mysqlDBEntity,转换异常


真实开发环境中,可以有2个开发人员,一个写mysql的保存,一个写redis的保存~



举了这么一个例子,其实就只是帮助大家稍微理解一下factoryBean干嘛的,相当于beanfactory.getbean这个返回的bean就是factorybean中getObject中返回的对象


那我们怎么才能够通过beanfactory获取factorybean呢,嘿嘿,其实beanfactory源码中已经有了说明:



通过前缀引用来区分本身和factoryBean,举例说明,如果一个bean叫做myJndiObject,那么getBean("myJndiObject")将获取该bean,如果getBean("&myJndiObject")将获取FactoryBean




修改上面的ProxyDBObjectTest.java

[java]  view plain  copy
  1. <span style="color:#000000;">package org.study.spring.factorybean;  
  2.   
  3. import org.junit.Test;  
  4. import org.springframework.beans.factory.FactoryBean;  
  5. import org.springframework.context.ApplicationContext;  
  6. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  7.   
  8. public class ProxyDBObjectTest{  
  9.       
  10.       
  11.     @Test  
  12.     public void test2() throws Exception{  
  13.          ApplicationContext applicationContext = new ClassPathXmlApplicationContext("factory-bean.xml");  
  14.          FactoryBean factoryBean =  applicationContext.getBean("&proxyDB",FactoryBean.class);  
  15.          DBOperation db = (DBOperation)factoryBean.getObject();  
  16.          MysqlDBEntity dbEntity = new MysqlDBEntity();  
  17.          db.save(dbEntity);  
  18.     }  
  19.   
  20. }</span>  
"&"符号可以获取本身,其实吧,BeanFactory和FactoryBean根本没有本质的关联,而且他们都是根接口,没有紧密的关系


关于FactoryBean在Aop中的运用,我们到了AOP再说,我们还是先分析IoC吧~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值