1. 程式人生 > >Spring BeanFactory與FactoryBean的區別及其各自的詳細介紹於用法

Spring BeanFactory與FactoryBean的區別及其各自的詳細介紹於用法

排除 tle 判斷 service 關系 符號 它的 extc ()

1. BeanFactory

  BeanFactory,以Factory結尾,表示它是一個工廠類(接口),用於管理Bean的一個工廠。在Spring中,BeanFactory是IOC容器的核心接口,它的職責包括:實例化、定位、配置應用程序中的對象及建立這些對象間的依賴。

  Spring為我們提供了許多易用的BeanFactory實現,XmlBeanFactory就是常用的一個,該實現將以XML方式描述組成應用的對象及對象間的依賴關系。XmlBeanFactory類將持有此XML配置元數據,並用它來構建一個完全可配置的系統或應用。

  實例化容器

1 Resource resource = new FileSystemResource("beans.xml");
2 BeanFactory factory = new XmlBeanFactory(resource);
1 ClassPathResource resource = new ClassPathResource("beans.xml");
2 BeanFactory factory = new XmlBeanFactory(resource);
1 ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml", "applicationContext-part2.xml"});
3 BeanFactory factory = (BeanFactory) context;

基本就是這些了,接著使用getBean(String beanName)方法就可以取得bean的實例;BeanFactory提供的方法及其簡單,僅提供了六種方法供客戶調用:

  •   boolean containsBean(String beanName) 判斷工廠中是否包含給定名稱的bean定義,若有則返回true
  •   Object getBean(String) 返回給定名稱註冊的bean實例。根據bean的配置情況,如果是singleton模式將返回一個共享實例,否則將返回一個新建的實例,如果沒有找到指定bean,該方法可能會拋出異常
  •   Object getBean(String, Class) 返回以給定名稱註冊的bean實例,並轉換為給定class類型
  •   Class getType(String name) 返回給定名稱的bean的Class,如果沒有找到指定的bean實例,則排除NoSuchBeanDefinitionException異常
  •   boolean isSingleton(String) 判斷給定名稱的bean定義是否為單例模式
  •   String[] getAliases(String name) 返回給定bean名稱的所有別名

2. FactoryBean

  以Bean結尾,表示它是一個Bean,不同於普通Bean的是:它是實現了FactoryBean<T>接口的Bean,根據該Bean的ID從FactoryBean中獲取的實際上是FactoryBean的getObject()返回的對象,而不是FactoryBean本身,如果要獲取FactoryBean對象,請在id前面加一個&符號來獲取。

  例如自己實現一個FactoryBean,功能:用來代理一個對象,對該對象的所有方法做一個攔截,在調用前後都輸出一行LOG,模仿ProxyFactoryBean的功能。

技術分享圖片
 1 /**
 2  * my factory bean<p>
 3  * 代理一個類,攔截該類的所有方法,在方法的調用前後進行日誌的輸出
 4  * @author daniel.zhao
 5  *
 6  */
 7 public class MyFactoryBean implements FactoryBean<Object>, InitializingBean, DisposableBean {
 8 
 9     private static final Logger logger = LoggerFactory.getLogger(MyFactoryBean.class);
10     
11     private String interfaceName;
12     
13     private Object target;
14     
15     private Object proxyObj;
16     
17     @Override
18     public void destroy() throws Exception {
19         logger.debug("destroy......");
20     }
21 
22     @Override
23     public void afterPropertiesSet() throws Exception {
24         proxyObj = Proxy.newProxyInstance(
25                 this.getClass().getClassLoader(), 
26                 new Class[] { Class.forName(interfaceName) }, 
27                 new InvocationHandler() {
28                     
29             @Override
30             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
31                 logger.debug("invoke method......" + method.getName());
32                 logger.debug("invoke method before......" + System.currentTimeMillis());
33                 Object result = method.invoke(target, args);
34                 logger.debug("invoke method after......" + System.currentTimeMillis());
35                 return result;
36             }
37             
38         });
39         logger.debug("afterPropertiesSet......");
40     }
41 
42     @Override
43     public Object getObject() throws Exception {
44         logger.debug("getObject......");
45         return proxyObj;
46     }
47 
48     @Override
49     public Class<?> getObjectType() {
50         return proxyObj == null ? Object.class : proxyObj.getClass();
51     }
52 
53     @Override
54     public boolean isSingleton() {
55         return true;
56     }
57 
58     public String getInterfaceName() {
59         return interfaceName;
60     }
61 
62     public void setInterfaceName(String interfaceName) {
63         this.interfaceName = interfaceName;
64     }
65 
66     public Object getTarget() {
67         return target;
68     }
69 
70     public void setTarget(Object target) {
71         this.target = target;
72     }
73 
74     public Object getProxyObj() {
75         return proxyObj;
76     }
77 
78     public void setProxyObj(Object proxyObj) {
79         this.proxyObj = proxyObj;
80     }
81 
82 }
技術分享圖片

XML-Bean配置如下

1 <bean id="fbHelloWorldService" class="com.ebao.xxx.MyFactoryBean">
2     <property name="interfaceName" value="com.ebao.xxx.HelloWorldService" />
3     <property name="target" ref="helloWorldService" />
4 </bean>

Junit Test class

技術分享圖片
 1 @RunWith(JUnit4ClassRunner.class)
 2 @ContextConfiguration(classes = { MyFactoryBeanConfig.class })
 3 public class MyFactoryBeanTest {
 4 
 5     @Autowired
 6     private ApplicationContext context;
 7     
 8     /**
 9      * 測試驗證FactoryBean原理,代理一個servcie在調用其方法的前後,打印日誌亦可作其他處理
10      * 從ApplicationContext中獲取自定義的FactoryBean
11      * context.getBean(String beanName) ---> 最終獲取到的Object是FactoryBean.getObejct(), 
12      * 使用Proxy.newInstance生成service的代理類
13      */
14     @Test
15     public void testFactoryBean() {
16         HelloWorldService helloWorldService = (HelloWorldService) context.getBean("fbHelloWorldService");
17         helloWorldService.getBeanName();
18         helloWorldService.sayHello();
19     }
20 }
技術分享圖片

其實FactoryBean這棟特點,可以實現很多有用的功能,實現大家多多評論多多補充,一起探討。

Spring BeanFactory與FactoryBean的區別及其各自的詳細介紹於用法