浅析Spring IoC源码(七)浅谈BeanFactory和FactoryBean
  fztgkkRjHIsV 2023年11月14日 20 0



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

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

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

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


这个接口有多重要?

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

看看这段:这个接口在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


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


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


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. "save object to mysql");  
12. return 1;  
13.     }  
14.   
15. public int update(MysqlDBEntity t) {  
16. "update object to mysql");  
17. return 0;  
18.     }  
19.   
20. public int delete(MysqlDBEntity t) {  
21. "delete object from mysql");  
22. return 0;  
23.     }  
24.   
25. public MysqlDBEntity select(Integer id) {  
26. return new MysqlDBEntity();  
27.     }  
28. }</span>

RedisDB.java



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. "save this object"+t.getJsonStr());  
13. return 1;  
14.     }  
15.   
16. public int update(RedisDBEntity t) {  
17. "update this object"+t.getJsonStr());  
18. return 0;  
19.     }  
20.   
21. public int delete(RedisDBEntity t) {  
22. "delete this object"+t.getJsonStr());  
23. return 1;  
24.     }  
25.   
26. public RedisDBEntity select(Integer id) {  
27. "select this object by id "+id);  
28. return new RedisDBEntity();  
29.     }  
30.       
31.   
32. }</span>


MysqlDBEntity.java




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




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


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


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. >  
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


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

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. new ClassPathXmlApplicationContext("factory-bean.xml");  
13. "proxyDB",DBOperation.class);  
14. new MysqlDBEntity();  
15.          dBoperation.save(dbEntity);  
16.     }  
17.   
18. }

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

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

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

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

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

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

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

修改上面的ProxyDBObjectTest.java


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. new ClassPathXmlApplicationContext("factory-bean.xml");  
14. "&proxyDB",FactoryBean.class);  
15.          DBOperation db = (DBOperation)factoryBean.getObject();  
16. new MysqlDBEntity();  
17.          db.save(dbEntity);  
18.     }  
19.   
20. }</span>


"&"符号可以获取本身,其实吧,BeanFactory和FactoryBean根本没有本质的关联,而且他们都是根接口,没有紧密的关系

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


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月14日 0

暂无评论

推荐阅读
fztgkkRjHIsV