1. 程式人生 > >BeanFactory 與 FactoryBean的區別及FactoryBean詳解

BeanFactory 與 FactoryBean的區別及FactoryBean詳解

原文地址:http://blog.csdn.net/is_zhoufeng/article/details/38422549

首先要分辨BeanFactory 與 FactoryBean的區別, 兩個名字很像,所以容易搞混

BeanFactory: 以Factory結尾,表示它是一個工廠類,是用於管理Bean的一個工廠

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

Spring中的Bean有兩種。

一種是普通的bean ,比如配置

  1. <beanid="personService"class="com.spring.service.impl.PersonServiceImpl"scope="prototype">
  2.             <propertyname="name"value="is_zhoufeng"/>
  3.       </bean>
那個使用BeanFactory根據id personService獲取bean的時候,得到的物件就是PersonServiceImpl型別的。

另外一種就是實現了org.springframework.beans.factory.FactoryBean<T>介面的Bean , 那麼在從BeanFactory中根據定義的id獲取bean的時候,獲取的實際上是FactoryBean介面中的getObject()方法返回的物件。

以Spring提供的ProxyFactoryBean為例子,配置如下:

  1. <beanid="personServiceByLog"class="org.springframework.aop.framework.ProxyFactoryBean">
  2.             <propertyname="proxyInterfaces">
  3.                 <list>
  4.                     <value>com.spring.service.PersonService</value>
  5.                 </
    list>
  6.             </property>
  7.             <propertyname="interceptorNames">
  8.                 <list>
  9.                     <value>logInteceptor</value>
  10.                     <value>ZFMethodAdvice</value>
  11.                 </list>
  12.             </property>
  13.             <propertyname="targetName"value="personService"/>
  14.      </bean>

那麼在程式碼中根據personServiceByLog來獲取的Bean實際上是PersonService型別的。 
  1. @Test
  2.  publicvoid test01() {  
  3.      PersonService ps = context.getBean("personService", PersonService.class);  
  4.      ps.sayHello();  
  5.      String name = ps.getName();  
  6.      System.out.println(name);  
  7.  }  

如果要獲取ProxyFactoryBean本身,可以如下
  1. @Test
  2.  publicvoid test04() {  
  3.      ProxyFactoryBean factoryBean = context.getBean("&personServiceByLog", ProxyFactoryBean.class);  
  4.      PersonService ps = (PersonService) factoryBean.getObject();  
  5.      String name = ps.getName();  
  6.      System.out.println(name);  
  7.  }  


自己實現一個FactoryBean, 功能:用來代理一個物件,對該物件的所有方法做一個攔截,在方法呼叫前後都輸出一行log

  1. package com.spring.factorybean;  
  2. import java.lang.reflect.InvocationHandler;  
  3. import java.lang.reflect.Method;  
  4. import java.lang.reflect.Proxy;  
  5. import org.springframework.beans.factory.DisposableBean;  
  6. import org.springframework.beans.factory.FactoryBean;  
  7. import org.springframework.beans.factory.InitializingBean;  
  8. publicclass ZFFactoryBean implements FactoryBean<Object>, InitializingBean, DisposableBean {  
  9.     // 被代理物件實現的介面名(在使用Proxy時需要用到,用於決定生成的代理物件型別)
  10.     private String interfaceName;  
  11.     // 被代理的物件
  12.     private Object target;  
  13.     // 生成的代理物件
  14.     private Object proxyObj;  
  15.     publicvoid destroy() throws Exception {  
  16.         System.out.println("distory...");  
  17.     }  
  18.     publicvoid afterPropertiesSet() throws Exception {  
  19.         proxyObj = Proxy.newProxyInstance(this.getClass().getClassLoader(),  
  20.                                           new Class[] { Class.forName(interfaceName) }, new InvocationHandler() {  
  21.                                               public Object invoke(Object proxy, Method method, Object[] args)  
  22.                                                                                                               throws Throwable {  
  23.                                                   System.out.println("method:" + method.getName());  
  24.                                                   System.out.println("Method before...");  
  25.                                                   Object result = method.invoke(target, args);  
  26.                                                   System.out.println("Method after...");  
  27.                                                   return result;  
  28.                                               }  
  29.                                           });  
  30.         System.out.println("afterPropertiesSet");  
  31.     }  
  32.     public Object getObject() throws Exception {  
  33.         System.out.println("getObject");  
  34.         return proxyObj;  
  35.     }  
  36.     public Class<?> getObjectType() {  
  37.         return proxyObj == null ? Object.class : proxyObj.getClass();  
  38.     }  
  39.     publicboolean isSingleton() {  
  40.         returntrue;  
  41.     }  
  42.     public String getInterfaceName() {  
  43.         return interfaceName;  
  44.     }  
  45.     publicvoid setInterfaceName(String interfaceName) {  
  46.         this.interfaceName = interfaceName;  
  47.     }  
  48.     public Object getTarget() {  
  49.         return target;  
  50.     }  
  51.     publicvoid setTarget(Object target) {  
  52.         this.target = target;  
  53.     }  
  54. }  
然後來試試:

首先這樣定義bean

  1. <bean id="personService"class="com.spring.service.impl.PersonServiceImpl" scope="prototype">  
  2.             <property name="name" value="is_zhoufeng" />  
  3.       </bean>    
  4.       <bean id="zfPersonService"class="com.spring.factorybean.ZFFactoryBean">  
  5.         <property name="interfaceName" value="com.spring.service.PersonService" />  
  6.         <property name="target"  ref="personService"/>  
  7.       </bean>  
然後獲取Bean,並測試。
  1. @Test
  2.  publicvoid test06() {  
  3.      PersonService ps = context.getBean("zfPersonService", PersonService.class);  
  4.      ps.sayHello();  
  5.      String name = ps.getName();  
  6.      System.out.println(name);  
  7.  }  

會發現sayHello與getName方法呼叫前後都有log列印。

上面的ZFBeanFactory只是模仿了ProxyFactoryBean的功能做了一個實現而已。

其實通過FactoryBean這種特點,可以實現很多有用的功能 。。。


相關推薦

Linux下ps -ef和ps aux的區別格式

占用內存 style star wid 內存交換 現在 linu pts tar Linux下顯示系統進程的命令ps,最常用的有ps -ef 和ps aux。這兩個到底有什麽區別呢?兩者沒太大差別,討論這個問題,要追溯到Unix系統中的兩種風格,System V風格和BSD

Linux下ps -ef和ps aux的區別格式-轉

進程組 inux 詳解 少見 CP 被鎖 中斷 https www. 原文:https://www.linuxidc.com/Linux/2016-07/133515.htm Linux下顯示系統進程的命令ps,最常用的有ps -ef 和ps aux。這兩個到底有什麽區別呢

sizeof和strlen的區別使用

首先我們來看一下sizeof和strlen的區別: sizeof操作符的結果型別為size_t(The sizeof keyword gives the amount of storage, in bytes, associated with a varia

hadoop的三種執行模式區別配置

       基於hadoop進行開發時,有時候,會被hadoop的三種執行模式搞混,也會被hadoop叢集有哪些配置弄得暈頭轉向,因為看不同的文件有不同的配置方法。所以要先弄明白hadoop的執行模

BeanFactory FactoryBean區別FactoryBean

原文地址:http://blog.csdn.net/is_zhoufeng/article/details/38422549 首先要分辨BeanFactory 與 FactoryBean的區別, 兩個名字很像,所以容易搞混 BeanFactory: 以Factory結

【Spring原始碼解讀】BeanFactoryFactoryBean區別類裝載原始碼解讀

最近讀程式碼讀到Bean裝載過程,順帶上網搜了下BeanFactory和FactoryBean,發現好多文章都講的不清不楚,特此自己來整理了一份BeanFactory和FactoryBean的區別及講下bean的裝載和讀取過程的原始碼.     首先來

梯度下降隨機梯度下降概念推導過程

        同這一張的梯度下降部分加起來,才是我們要講的如何求解多元線性迴歸.如果寫在一章中,內容過長,擔心有的同學會看不完,所以拆分成兩章.[壞笑]         上一章中有提到利用解析解求解多元線性迴歸,雖然看起來很方便,但是在解析解求解的過程中會涉及到矩陣求

日期操作類(DateFormatSimpleDateFormat)的區別和使用

                     你也可以檢視我的其他同類文章,也會讓你有一定的收貨一、DateFormat類此類是一個日期的格式化類,用來格式化日期。具體日期可以通過java.util.Date類來獲取。DateFormat類的定義:此類是定義在java.test包中的。public abstrac

NginxPHP(php-fpm)工作機制原理

一、代理與反向代理 現實生活中的例子 1、正向代理:訪問google.com 如上圖,因為目前google已被和諧,我們需要vpn才能科學訪問google.com。 vpn對於“我們”來說,是可以感知到的(我們連線vpn)vpn對於”google伺服器”來說,是不可感知的(

MySQL傳統複製GTID複製原理操作

mysql複製在業界裡有叫:mysql同步,ab複製等。專業名稱就是叫:複製 複製是單向的,只能從master複製到slave上,延時基本上是毫秒級別的。 一組複製結構中可以有多個slave,對於master一般場景推薦只有一個。 master使用者寫入資料,生成event記到binary log中 sla

資料結構圖文解析之:哈夫曼樹哈夫曼編碼C++模板實現

0. 資料結構圖文解析系列 1. 哈夫曼編碼簡介 哈夫曼編碼(Huffman Coding)是一種編碼方式,也稱為“赫夫曼編碼”,是David A. Huffman1952年發明的一種構建極小多餘編碼的方法。 在計算機資料處理中,霍夫曼編碼使用變長編碼表對源符號進行編碼,出現頻率較高的源符號採用較短的編碼,

Windows下安裝Resin配置釋出應用

    關於Resin的好處,網上介紹了一大堆,小編經不住誘惑,決定試用一下。目前Resin的最新版本為:4.0.40,可以從官網直接下載。     1. 將下載下來的Resin包解壓開,會看到一大堆的檔案,有一些關鍵的檔案,我們需要了解一下。 resin-4.0.4

getClass()和getClassLoader()區別 以及ClassLoader用途(檔案載入,類載入)

 1.1 幾個相關概念ClassLoader負責載入系統的所有Resources(Class,檔案,來自網路的位元組流等),通過ClassLoader從而將資源載入JVM   每個class都有一個reference,指向自己的ClassLoader。Class.getClassLoader()   arra

Python多程序多執行緒程式設計GIL

介紹如何使用python的multiprocess和threading模組進行多執行緒和多程序程式設計。 Python的多程序程式設計與multiprocess模組 python的多程序程式設計主要依靠multiprocess模組。我們先對比兩段程式碼,看看多程序程式設計的優勢。我們模擬了一個非常耗時的任

coco標註資訊labelme標註資訊的、相互轉換視覺化

引言 在做例項分割或語義分割的時候,我們通常要用labelme進行標註,labelme標註的json檔案與coco資料集已經標註好的json檔案的格式和內容有差異。如果要用coco資料集的資訊,就要對json檔案進行修改和轉換。本部落格提供兩種格式的具體內容及含義以及兩種格式相互轉換的程式碼,並對兩種格式的j

【Spring】Spring MVC原理配置

進行 return sub sca scrip uil 線程安全 松耦合 必須 1.Spring MVC概述: Spring MVC是Spring提供的一個強大而靈活的web框架。借助於註解,Spring MVC提供了幾乎是POJO的開發模式,使得控制器的開發和測試更加簡

php冒泡排序快速排序實例

lag ++ function 開始 ret light 記錄 php冒泡排序 php $a=array(‘3‘,‘8‘,‘1‘,‘4‘,‘11‘,‘7‘); print_r($a); $len = count($a); //從小到大 for($i=1;$i<$le

緩存varnish的管理配置

啟動 一個 hint 單位 quad spec int rom try 一 工作原理 在當前主流的Web服務架構體系中,Cache擔任著越來越重要的作用。常見的基於瀏覽器的C/S架構,Web Cache更是節約服務器資源的關鍵。而最近幾年由FreeBSD創始人之一Kamp開

第三講 html編輯器body

原則 eight enter 一個 width html標記 ctr script mysq 最好的學習方法:學思路 1.制作網頁的方法: 新建記事本或者用“editplus編輯器”. edi

常用 JavaScript 小技巧原理

this lin slice pen global 轉化 script lis fun 善於利用JS中的小知識的利用,可以很簡潔的編寫代碼 1. 使用!!模擬Boolean()函數 原理:邏輯非操作一個數據對象時,會先將數據對象轉換為布爾值,然後取反,兩個!!重復取反,就實