IOC容器

一、IOC概述

  1. 概念:控制反轉(Inverse of Control)DI 依賴注入

    某一接口具體實現類的選擇控制權從調用類中移除,轉交給spring容器由Bean配置來進行控制。


  2. IOC的類型:構造函數注入、屬性注入、接口注入。


  3. 通過容器完成依賴注入:通過new XmlBeanFactory("beans.xml")等方式啓動容器,在容器啓動時,spring根據配置文件的描述信息,自動實例化bean並完成依賴關係的裝配,從容器中即可返回Bean實例。



二、相關的Java基礎知識

  1. 類裝載器:Class文件由類加載器裝載後,在JVM中將形成一份描述Class結構的元信息對象,通過該元信息對象可以獲取Class的結構信息。用戶藉助這個元信息對象間接調用Class對象的功能。


  2. 類裝載器的工作機制和方法

    根裝載器使用C++編寫,在java中看不到,它負責裝載JRE的核心類庫。根裝載器->ExtClassLoader->AppClassLoader。JVM使用全盤負責委託機制。先委託父裝載器,沒法再有子。


三、資源訪問器

  1.spring設計了一個Resource接口,exitst()資源是否存在、isOpen()資源是否打開、getURL()、getFile()、getInputStream()返回資源對應的輸入流。

  如果有一個文件位於Web應用的類路徑下,用戶可以通過以下方式訪問:

  1)通過FileSystemResource以文件系統絕對路徑的方式進行訪問。

  2)通過ClassPathResource以類路徑的方式進行訪問。

  3)通過ServletContextResource以相對於web應用根目錄的方式進行訪問。


   在獲取資源後,用戶可以通過Resource接口定義的方法訪問文件的數據和信息。getFileName()獲取文件名、getFile()獲取File對象、getInputStream()獲取文件的輸入流。

   而WritableResource接口,通過getOutputStream()方法直接獲取文件的輸入流。

public class FileSourceExample {
   
   public static void main(String[] args) {
      try {

         String filePath = "D:/cnslp/hello.txt";
         //使用系統文件路徑方式加載文件
         WritableResource res1 = new PathResource(filePath);
         //使用類路徑方式加載文件
         Resource res2 = new ClassPathResource("conf/file1.txt");

         //使用WritableResource接口寫資源文件
         OutputStream stream1 = res1.getOutputStream();
         stream1.write("歡迎光臨\ncnslp論壇".getBytes());
         stream1.close();
         
         //使用Resource接口讀取資源文件
            InputStream ins1 = res1.getInputStream();
         InputStream ins2 = res2.getInputStream();

         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         int i;
         while((i=ins1.read())!=-1){
            baos.write(i);
         }
         System.out.println(baos.toString());

            System.out.println("res1:"+res1.getFilename());
            System.out.println("res2:"+res2.getFilename());            
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

   2.通過EncodeResource對資源進行編碼,以保證內容的正確性。

Resource res = new ClassPathResource("conf/file1.txt");
EncodedResource encRes = new EncodedResource(res,"UTF-8");//使用UTF-8編碼
String content  = FileCopyUtils.copyToString(encRes.getReader());
System.out.println(content);

   3.資源加載

    通過資源地址的特殊標識來訪問相對應的資源

    1)classpath:從類路徑中加載資源,classpath:和classpath:/是等價的;

    2)file: 使用url從文件系統目錄中裝載資源;

    3)http:// 使用UrlResource從web服務器中裝載資源;

    4)ftp://  使用UrlResource從FTP服務器中裝載資源;
注意:classpath*:會掃描所有jar包及類路徑;

Ant風格:?匹配文件名的一個字符

     *匹配文件名中任意字符

     **匹配多層路徑

ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource resource = resolver.getResource("classpath:conf/file1.txt");
System.out.println(resource.getFilename());
System.out.println(resource.getDescription());

注意:使用Resource操作文件,如果項目發佈打包,則不能使用Resource的getFile()方法,應該使用getInputStream()來讀取。


四、BeanFactory和ApplicationContext

  應用上下文建立在BeanFactory基礎上,一般稱BeanFactory爲IOC容器、ApplicationContext爲應用上下文或者spring容器。

  1.BeanFactory類的通用工廠,不過開發一般直接使用ApplicationContext

  2.ApplicationContext

  1)ApplicationContext類的體系結構

  ApplicationContext的主要實現類是ClassPathXmlApplicationContext(默認從類路徑加載配置文件)和FileSystemXmlApplicationContext(默認從文件系統中裝載配置文件)

注:BeanFactory在初始化容器時,並未實例化bean,直到第一次使用才實例化,而ApplicationContext則在初始化上下文的時候就實例化bean。

@Configuration//表示是一個配置信息提供類
public class Beans {

   @Bean(name = "car")//定義一個Bean
   public Car buildCar() {
      Car car = new Car();
      car.setBrand("紅旗CA72");
      car.setMaxSpeed(200);
      return car;
   }
}
public static void main(String[] args) {
   //通過一個帶@Configuration的POJO裝載Bean配置
   ApplicationContext ctx = new AnnotationConfigApplicationContext(Beans.class);
   Car car =ctx.getBean("car",Car.class);
}


  2)WebApplicationContext類的體系結構

  WebApplicationContext專門爲web應用準備的,它允許從相對應Web根目錄路徑中裝配配置文件完成初始化。WebApplicationContext初始化需要ServletContext實例,必須在web容器的前提下才能完成啓動工作,在web.xml中配置自啓動的Servlet或定義Web容器監聽器可以完成啓動spring web應用上下網的工作。

  由於WebApplicationContext需要使用日誌功能,所以用戶把log4j的配置文件放在WEB-INF/classes下,這時log4j引擎即可順利啓動。如果log4j配置文件放在其他位置,需要在web.xml中指定器位置。

<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.properties</param-value>
</context-param>

<servlet>
    <servlet-name>log4jServlet</servlet-name>
    <servlet-class>org.springframework.web.util.Log4jConfigServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet>
    <servlet-name>springServlet</servlet-name>
    <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>

對於<context-param>主要是用來定義全局變量給整個項目共用

  • 容器初始化過程:

    1. 在啓動Web項目時,容器(比如Tomcat)會讀web.xml配置文件中的兩個節點<listener>和<contex-param>。

    2. 接着容器會創建一個ServletContext(上下文),應用範圍內即整個WEB項目都能使用這個上下文。

    3. 接着容器會將讀取到<context-param>轉化爲鍵值對,並交給ServletContext。

    4. 容器創建<listener></listener>中的類實例,即創建監聽(備註:listener定義的類可以是自定義的類但必須需要繼承ServletContextListener)。

    5. 在監聽的類中會有一個contextInitialized(ServletContextEvent event)初始化方法,在這個方法中可以通過event.getServletContext().getInitParameter("contextConfigLocation") 來得到context-param 設定的值。在這個類中還必須有一個contextDestroyed(ServletContextEvent event) 銷燬方法.用於關閉應用前釋放資源,比如說數據庫連接的關閉。

    6. 得到這個context-param的值之後,你就可以做一些操作了.注意,這個時候你的WEB項目還沒有完全啓動完成.這個動作會比所有的Servlet都要早。

容器對於web.xml的加載過程是context-param >> listener  >> fileter  >> servlet

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章