Java 依賴注入總結

最近在研讀Hive社區版本的源碼,發現其中多處用到了Java依賴注入,這里簡單總結一下依賴注入的幾種實現方法。在談java依賴注入之前,有必要先回顧一下設計模式中的Proxy模式。

其實每個模式名稱就表明了該模式的作用,代理模式就是多一個代理類出來,替原對象進行一些操作,比如我們在租房子的時候回去找中介,為什么呢?因為你對該地區房屋的信息掌握的不夠全面,希望找一個更熟悉的人去幫你做,此處的代理就是這個意思。再如我們有的時候打官司,我們需要請律師,因為律師在法律方面有專長,可以替我們進行操作,表達我們的想法。先來看看關系圖:

image.png

根據上文的闡述,代理模式就比較容易的理解了,我們看下代碼:

public interface Sourceable {
    public void method();
}
   @Override
    public void method() {
        System.out.println("the original method!");
    }
 public class Proxy implements Sourceable {

    private Source source;
    public Proxy(){
        super();
        this.source = new Source();
    }
    @Override
    public void method() {
        before();
        source.method();
        atfer();
    }
    private void atfer() {
        System.out.println("after proxy!");
    }
    private void before() {
        System.out.println("before proxy!");
    }
}

測試類

public class ProxyTest {

    public static void main(String[] args) {
        Sourceable source = new Proxy();
        source.method();
    }

}

輸出:

before proxy!
the original method!
after proxy!

代理模式的應用場景:

如果已有的方法在使用的時候需要對原有的方法進行改進,此時有兩種辦法:

1、修改原有的方法來適應。這樣違反了“對擴展開放,對修改關閉”的原則。

2、就是采用一個代理類調用原有的方法,且對產生的結果進行控制。這種方法就是代理模式。

使用代理模式,可以將功能劃分的更加清晰,有助于后期維護!

下面我們要說的Java依賴注入可以說就是proxy模式的一種應用,這里總結一下常用的三種依賴注入方法

1. 接口注入

我們常常借助接口來將調用者與實現者分離。如:

public class ClassA {
private InterfaceB clzB;
public init() {
    Ojbect obj =
    Class.forName(Config.BImplementation).newInstance();
    clzB = (InterfaceB)obj;
}
……
}

上面的代碼中,ClassA依賴于InterfaceB 的實現,如何獲得InterfaceB 實現類的實例?傳統的方法是在代碼中創建InterfaceB 實現類的實例,并將起賦予clzB。而這樣一來,ClassA在編譯期即依賴于InterfaceB 的實現。為了將調用者與實現者在編譯期分離,于是有了上面的代碼,我們根據預先在配置文件中設定的實現類的類名,動態加載實現類,并通過InterfaceB 強制轉型后為ClassA所用。
這就是接口注入的一個最原始的雛形。而對于一個接口注入型IOC容器而言,加載接口實現并創建其實例的工作由容器完成,如J2EE開發中常用的Context.lookup(ServletContext.getXXX),都是接口注入型IOC的表現形式。
Apache Avalon是一個典型的Type1型IOC容器。

2. 構造子注入

構造子注入,即通過構造函數完成依賴關系的設定,如:

 public class DIByConstructor {
private final DataSource dataSource;
private final String message;
public DIByConstructor(DataSource ds, String msg) {
    this.dataSource = ds;
    this.message = msg;
}
……
}

可以看到,在Type2類型的依賴注入機制中,依賴關系是通過類構造函數建立,容器通過調用類的構
造方法,將其所需的依賴關系注入其中。
PicoContainer(另一種實現了依賴注入模式的輕量級容器)首先實現了Type2類型的依賴注入模式。

3. 設置注入

這種方式廣泛應用在Spring框架的參數配置中,客戶代碼僅僅面向接口編程,而無需知道實現類的具體名稱。同時,我們可以很簡單的通過修改配置文件來切換具體的底層實現類。下面我們拋開Spring框架本身,使用一個簡單的例子來實現類似Spring的依賴注入
public class ActionFactory {
    public static Action getAction(String actionName) {
      Properties pro = new Properties();
      try {
        pro.load(new FileInputStream("config.properties"));
        String actionImplName = (String) pro.get(actionName);
        String actionMessage = (String) pro.get(actionName + "_msg");
        Object obj = Class.forName(actionImplName).newInstance();

        // BeanUtils是Apache Commons BeanUtils提供的輔助類
        BeanUtils.setProperty(obj, "message", actionMessage);
        return (Action) obj;
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      } catch (ClassNotFoundException e) {
        e.printStackTrace();
      } catch (InstantiationException e) {
        e.printStackTrace();
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      } catch (InvocationTargetException e) {
        e.printStackTrace();
      }
      return null;
    }
  }

配置文件則采用最簡單的properties文件形式:
TheAction=net.xiaxin.spring.qs.UpperAction
TheAction_msg=HeLLo

測試類:

public void testFactory(){
    Action action = ActionFactory.getAction("TheAction");
    System.out.println(action.execute("Rod Johnson"));
}

上面的例子中,我們通過設置注入,在運行期動態將字符串“HeLLo” 注入到Action實現類的Message屬性中。用同樣的方法,我們可以通過修改配置文件讓程序調用不同的實現方法,從而實現靈活的依賴注入。在Hive源碼中,HiveDriverRunHook類也是使用這種方式實現注入的

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,828評論 18 139
  • 從三月份找實習到現在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發崗...
    時芥藍閱讀 42,339評論 11 349
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,737評論 18 399
  • 這部分主要是開源Java EE框架方面的內容,包括Hibernate、MyBatis、Spring、Spring ...
    雜貨鋪老板閱讀 1,417評論 0 2
  • 看到朋友說到師太的書,我回憶起我買了那么多師太的書,經過幾次搬家,書已經落得七七八八,最后留在我手上的,一本都無,...
    阿拉97閱讀 269評論 2 2