成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

IoC容器總結與簡單模擬

開發 后端
當一個組件需要外部資源時,最直接也最明智的方法是執行查找,這種行為稱為主動查找。但這種查找存在一個缺點——組件需要知道如何獲得資源。那么它的解決方案是什么呢?請看下文。

當一個組件需要外部資源時,最直接也最明智的方法是執行查找,這種行為稱為主動查找。但這種查找存在一個缺點——組件需要知道如何獲得資源。一個好的獲取資源的解決方案是應用IoC(Inversion of Control,控制反轉)。它的思想是反轉資源獲取的方向。傳統的資源查找方式是要求組件向容器發起請求來查找資源,作為回應,容器適時的返回資源。而應用了IoC之后,則是容器主動的將資源推送到它所管理的組件里,組件所要做的僅僅是選擇一種合適的方式接受資源。

IoC是一種通用的設計原則,而DI(Dependency Injection,依賴注入)則是具體的設計模式,它體現了IoC的設計原則。DI是IoC典型的實現,所以IoC與DI術語會被混用。IoC與DI的關系就好比Java中的"接口"和"接口的實現類"的關系一樣。

在DI模式下,容器全權負責的組件的裝配,容器以一些預先定義好的方式(例如setter方法或構造函數)將匹配的資源注入到每個組件里。目前有三種類型的DI:

setter注入,setter注入會存在一些問題,1. 容易出現忘記調用setter方法注入組件所需要的依賴,將會導致NullPointerException異常。2. 代碼會存在安全問題,第一次注入后,不能阻止再次調用setter,除非添加額外的處理工作。但是由于setter注入非常簡單所以非常流行(絕大多數Java IDE都支持自動生成setter方法)。
構造器注入,構造器注入能夠一定程度上解決setter注入的問題。但是該中注入方式也會帶來一些問題,如果組件有很多的依賴,則構造函數的參數列表將變得冗長,會降低代碼可讀性。
接口注入 ,該注入方式使用的非常少,它要求組件必須實現某個接口,容器正是通過這個接口實現注入依賴的。接口注入的缺點比較明顯,使用接口注入需要實現特定的接口,而接口又特定于容器,所以組件對容器產生了依賴,一旦脫離容器,組件不能重用。這是一種"侵入式"注入。

其中"setter注入"和"構造器注入"是被廣泛運用的,絕大多數的IoC容器都支持這兩種DI類型。

模仿Spring IoC容器

假設一個系統的功能之一是能夠生成PDF或HTML格式的報表。

  1. /*生成報表的通用接口*/ 
  2. public interface ReportBuilder  
  3. {  
  4.     public void build(String data);  

生成PDF和HTML格式的實現類:

  1. /*生成HTML格式報表*/ 
  2. public class ReportHtmlBuilder implements ReportBuilder {  
  3.     @Override 
  4.     public void build(String data) {  
  5.         /*示意代碼*/ 
  6.         System.out.println("build html report!");  
  7.     }  
  8. }  
  9.  
  10. /*生成PDF格式報表*/ 
  11. public class ReportPdfBuilder implements ReportBuilder {  
  12.     @Override 
  13.     public void build(String data) {  
  14.         System.out.println("build pdf report!");  
  15.     }  

報表服務類:

  1. /*報表服務類*/ 
  2. public class ReportService   
  3. {  
  4.     /*依賴"ReportBuilder"*/ 
  5.     private ReportBuilder builder;  
  6.       
  7.     public ReportBuilder getBuilder()  
  8.     {  
  9.         return builder;  
  10.     }  
  11.       
  12.     /*setter注入*/ 
  13.     public void setBuilder(ReportBuilder builder)  
  14.     {  
  15.         this.builder = builder;  
  16.     }  
  17.  
  18.     public void builderYearReport(int year)  
  19.     {  
  20.         this.builder.build("data");  
  21.     }  

IoC容器配置文件"component.properties"

  1. pdfBuilder=com.beliefbitrayal.ioc.inter.imp.ReportPdfBuilder  
  2. htmlBuilder=com.beliefbitrayal.ioc.inter.imp.ReportHtmlBuilder  
  3. reportService=com.beliefbitrayal.ioc.server.ReportService  
  4. reportService.builder=htmlBuilder 

IoC容器:

  1. public class Container  
  2. {  
  3.     /*用于儲存Component的容器*/ 
  4.     private Map<String, Object> repository = new HashMap<String, Object>();  
  5.  
  6.     public Container()  
  7.     {  
  8.         try 
  9.         {  
  10.             /*讀取容器配置文件"component.properties"*/ 
  11.             Properties properties = new Properties();  
  12.             properties.load(new FileInputStream("src/component.properties"));  
  13.               
  14.             /*獲取配置文件的每一行信息*/ 
  15.             for(Map.Entry<Object, Object> entry : properties.entrySet())  
  16.             {  
  17.                 String key = (String)entry.getKey();  
  18.                 String value = (String)entry.getValue();  
  19.                   
  20.                 /*處理配置文件的每一行信息*/ 
  21.                 this.handler(key, value);  
  22.             }  
  23.         }  
  24.         catch (Exception e)  
  25.         {  
  26.             e.printStackTrace();  
  27.         }  
  28.     }  
  29.       
  30.     private void handler(String key,String value) throws Exception  
  31.     {  
  32.         /*  
  33.          * reportService=com.beliefbitrayal.ioc.server.ReportService  
  34.          * reportService.builder=htmlBuilder  
  35.          * 第一種情況,key值中間沒有"."說明為一個新組件。對它的處理為創建它的對象,將其對象放入Map中。  
  36.          * 第二種情況,key值中間出現"."說明這個屬性條目是一個依賴注入。根據"."的位置將這個key值劃分為兩部分,第一部分為組件的名字,第二部分為  
  37.          * 該組件需要設置的屬性。  
  38.          */ 
  39.         String[] parts = key.split("\\.");  
  40.           
  41.         /*情況1*/ 
  42.         if(parts.length == 1)  
  43.         {  
  44.             /*通過反射的方式創建組件的對象*/ 
  45.             Object object = Class.forName(value).newInstance();  
  46.               
  47.             this.repository.put(key, object);  
  48.         }  
  49.         else 
  50.         {  
  51.             /*對于情況2,首先用key值的第一部分(組件名)獲取組件*/ 
  52.             Object object = this.repository.get(parts[0]);  
  53.               
  54.             /*再使用value值指定的組件名從Map對象中獲取依賴*/ 
  55.             Object reference = this.repository.get(value);  
  56.               
  57.             /*將獲取的依賴注入到指定的組件的相應屬性上,"PropertyUtils"類屬于Apache下Commons BeanUtil第三方類庫,  
  58.              * 要使用它還需要下載Commons Logging第三方類庫  
  59.              */ 
  60.             PropertyUtils.setProperty(object, parts[1], reference);  
  61.         }  
  62.     }  
  63.  
  64.     public Object getComponent(String key)  
  65.     {  
  66.         return this.repository.get(key);  
  67.     }  

根據配置文件,我們在場景類中使用的報表應該是HTML格式的:

  1. public class Client  
  2. {  
  3.     public static void main(String[] args)  
  4.     {  
  5.         /*創建容器*/ 
  6.         Container container = new Container();  
  7.           
  8.         /*從容器中獲取"報表服務類"*/ 
  9.         ReportService reportService = (ReportService)container.getComponent("reportService");  
  10.           
  11.         /*顯示報表*/ 
  12.         reportService.builderYearReport(0);  
  13.     }  

控制臺的輸出:

  1. build html report! 

我們若需要PDF格式的只需要修改屬性文件即可:

  1. pdfBuilder=com.beliefbitrayal.ioc.inter.imp.ReportPdfBuilder  
  2. htmlBuilder=com.beliefbitrayal.ioc.inter.imp.ReportHtmlBuilder  
  3. reportService=com.beliefbitrayal.ioc.server.ReportService  
  4. reportService.builder=pdfBuilder 

場景類不變,控制臺輸出:

  1. build pdf report! 

容器可以從基于文本的控制文件中讀取組件的定義,這使得容器可以重用。現在即使隨意改變組件的定義,都不用修改容器的代碼。這個例子很好的演示了IoC容器的核心原理和機制。

通過以上分析和舉例,控制反轉IoC就是一個組件的依賴是由容器來裝配,組件不做定位查詢,只提供普通的Java方法讓容器去裝配依賴關系,IoC容器是一般通過setter注入或構造函數注入的方式將依賴注入到組件中的,組件的依賴我們一般通過一個配置文件來描述(XML或Properties),配置文件在IoC容器被構建時讀取解析。

原文鏈接:http://www.cnblogs.com/beliefbetrayal/archive/2012/02/02/2335192.html

【編輯推薦】

  1. Java編程語言的認識誤區
  2. Java Thread的概述與總結
  3. Java路線圖:甲骨文的兩年計劃
  4. Java 8將支持無符號整型
  5. 深入研究Java虛擬機的類加載機制
責任編輯:林師授 來源: 信仰や欺騙的博客
相關推薦

2009-04-21 11:27:52

MVCJSPJDBC

2018-01-15 14:36:34

Linux負載CPU

2009-06-22 10:20:01

Spring IoC容

2013-07-05 14:47:51

IoC需求

2020-08-17 07:59:47

IoC DINestJS

2023-08-09 18:26:02

光纖綜合布線

2021-02-06 13:28:21

鴻蒙HarmonyOS應用開發

2021-01-14 18:17:33

SpringFrameIOCJava

2018-03-13 12:46:41

單模多模光纖

2023-08-16 17:44:38

2025-06-10 10:15:00

Java容器并發

2010-07-21 15:30:40

SQL Server

2025-03-14 10:37:24

SpringSpring IOC容器

2023-03-20 13:41:00

IoC容器Spring

2025-05-21 10:09:09

Spring 5.xIOC編程

2023-08-29 15:45:20

單模光纖多模光纖

2022-12-27 08:12:27

IOC容器Bean

2017-09-22 10:53:52

HTTPHTTP2TCP協議

2011-06-27 13:17:07

Java EE

2018-01-18 23:10:32

單模光纖多模光纖光纖
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美日韩专区 | 91精品国产乱码麻豆白嫩 | 国产黄色大片 | 日韩精品一区二区三区在线播放 | 日韩免费视频一区二区 | 国产精品久久久久久婷婷天堂 | 亚洲国产一区在线 | 伊人网站| 久久精品视频免费看 | 久久久www成人免费无遮挡大片 | 久草福利 | 精品国产一区二区三区久久 | 亚洲精品高清视频 | 国产精品一区二区在线观看 | 久久综合九色综合欧美狠狠 | 久久高清免费视频 | 日韩毛片免费看 | 午夜播放器在线观看 | 欧美精品久久久久久久久久 | 日日淫| 成人免费视屏 | 中文字幕黄色大片 | 国产一区二区在线观看视频 | 色婷婷亚洲一区二区三区 | 国产日韩欧美 | 国产成人网| 欧美日本在线 | av在线播放网站 | 毛片黄 | 久久久黄色 | 欧美黄色大片在线观看 | 夜操 | 超碰在线影院 | 久久91av | 在线a视频 | 国产成人99久久亚洲综合精品 | 一级特黄a大片 | 欧美精品网 | 成人国产精品久久久 | 久久欧美高清二区三区 | 国产一区免费 |