Spring學習筆記-IoC容器

  • IoC全稱爲控制反轉(Inverse of Control),也叫依賴注入,是spring容器的內核,AOP、事務等都依賴於此技術。IoC說白了,就是將對象與對象之間的依賴關係從代碼中轉移到spring的配置文件中(默認爲ApplicationContext.xml 也能夠自定義名字),從而由spring進行管理。這樣的好處就是下降了對象與對象之間的依賴。IoC的工做原理就是利用Java的反射功能實例化對象與對象的依賴。除此以外,IoC容器還提供了對象的實例緩存、生命週期管理、對象實例代理、事件發佈、資源裝載等高級功能。java

  • BeanFactory接口也就是你們熟知的Bean工廠,它是spring框架最核心的接口,它提供了高級的IoC配置機制,能夠管理任何不一樣類型的Java對象。ApplicationContext接口是繼BeanFactory接口以外,另外一個重要的接口。它的功能是創建在BeanFactory接口之上的。它除了已有的功能外,還提供國際化支持和框架事件等更多面嚮應用的功能。對於二者的區別用最直觀最簡介的方式來講就是BeanFactory是Spring框架的內核,它是給Spring用的,而ApplicationContext接口是給使用Spring框架的開發者用的。web

  • BeanFactory是一個類工廠,但它和通常的類工廠不一樣,通常的類工廠是實例化一個類或幾個類,而BeanFactory是個超級工廠,能夠建立管理各類類。全部被BeanFactory管理的對象在Spring中統稱爲Bean.下面咱們初始化BeanFactory工廠,並在工廠中獲取某個對象。spring


  • spring配置文件:bean.xml緩存

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 給car的全部屬性賦值 -->
    <bean id="car" class="com.xiaobai.spring.mark.Car" p:brand="衆泰T600S" p:color="白色" p:speed="120"></bean>

</beans>

  • 實體類Car.javasession

public class Car {
    /** 品牌 */
    private String brand;

    /** 顏色 */
    private String color;

    /** 速率 */
    private int speed;

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", color='" + color + '\'' +
                ", speed=" + speed +
                '}';
    }
}

  • 測試類CarTest.javaapp

public class CarTest {

    /**
     * new 方式實例化car對象
     */
    @Test
    public void newCreateCar() {
        Car car = new Car();
        car.setBrand("捷豹xjl");
        car.setColor("黑色");
        car.setSpeed(200);
        System.out.println(car);
    }

    /**
     * BeanFactory 方式實例化car對象
     */
    @Test
    public void beanFactoryCreateCar() {
        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        Resource resource = resourcePatternResolver.getResource("classpath:xiaobai/beans.xml");
        BeanFactory beanFactory = new XmlBeanFactory(resource);
        Car car = beanFactory.getBean("car", Car.class);
        System.out.println(car);
    }
    
    /**
     * applicationContext 方式實例化car對象
     */
    @Test
    public void applicationContextCreateCar() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:xiaobai/beans.xml");
        Car car = applicationContext.getBean("car", Car.class);
        System.out.println(car);
    }
}

  • XmlBeanFactory經過Resource裝載Spring配置信息並啓動IoC容器,而後經過BeanFactory中的getBean()方法從IoC容器中獲取Bean.根據Spring的內部機制,啓動IoC容器時,並不會初始化配置文件中的Bean.當第一次調用getBean()時初始化。對於單例的Bean來講,BeanFactory會緩存Bean實例,在第二次調用getBean()時,直接從IoC容器的緩存中獲取Bean實例。接下來咱們經過下面的例子來證實BeanFactory的緩存機制。框架


  • BeanFactory的緩存測試ide

ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
Resource resource = resourcePatternResolver.getResource("classpath:xiaobai/beans.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
Car car1 = beanFactory.getBean("car", Car.class);
Car car2 = beanFactory.getBean("car", Car.class);
System.out.println(car1);
System.out.println(car2);
  • 上述代碼咱們從IoC容器中獲取了兩個Car,經過輸出對象的內存地址信息來判斷這兩個car是否爲同一個測試

  • 輸出結果ui

com.xiaobai.spring.mark.Car@1d96f4b5
com.xiaobai.spring.mark.Car@1d96f4b5
  • 經過輸出結果證實了咱們以前所說的,BeanFactory的緩存機制。但在各別狀況下咱們不但願它有緩存,咱們但願每次訪問時返回的都是一個新的對象。那怎麼辦呢。咱們能夠經過scope屬性來配置。

  • beanx.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 給car添加scope屬性並值設置爲prototype -->
    <bean id="car" class="com.xiaobai.spring.mark.Car" p:brand="衆泰T600S" p:color="白色" p:speed="120" scope="prototype"></bean>
</beans>
  • 輸出結果

com.xiaobai.spring.mark.Car@6ecf829d
com.xiaobai.spring.mark.Car@79884a40
  • 經過結果咱們看,經過給Bean設置scope="prototype"時,IoC容器每次返回的都是一個新對象了,若是想每次返回的都是同一個對象,能夠設置爲scope="singleton",默認不設置scope屬性時scope="singleton"


  • Spring3.0之後支持類註解的配置方式,能夠經過@Configuration註解爲Spring提供配置信息,Spring爲配置的註解類提供了一個專門的實現類AnnotationConfigApplicationContext,下面咱們來看一下怎麼來加載配置信息

  • Beans.java

@Configuration
public class Beans {
    @Bean(name = "car")
    public Car buildCar() {
        Car car = new Car();
        car.setBrand("東風標誌508");
        car.setColor("白色");
        car.setSpeed(300);
        return car;
    }
}
  • 測試用例

/**
 * @Configuration 方式實例化car對象
 */
@Test
public void configurationCreateCar() {
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Beans.class);
    Car car = applicationContext.getBean("car", Car.class);
    System.out.println(car);
}
  • 輸出結果

Car{brand='東風標誌508', color='白色', speed=300}

  • WebApplicationContext接口是Spring專門爲Web應用準備的,它繼承了ApplicationContext接口,併爲Bean的scope屬性增長了三個值分別是request、session、globalSession.它容許從Web根目錄的路徑中裝載配置文件,完成初始化工做。由於它是爲Web服務的,因此它必須依賴於Web容器。根據Web項目開發經驗,咱們應該在web.xml配置自啓動的Servlet或者Web容器監聽器,來配置Web項目開發環境。Spring爲這兩種都提供了相應的類,來啓動Spring容器。它們分別爲org.springframework.web.context.ContextLoaderListener和org.springframework.web.context.ContextLoaderServlet.咱們能夠根據這兩種中的任何一種方式來啓動WebApplicationContext。雖然兩種沒有什麼太大的區別,均可以啓動WebApplicationContext,可是隻有Servlet2.3以上的版本的Web容器才支持Web容器的監聽器。(包括當前版本),因此能夠根據項目須要配置啓動WebApplicationContext的方式。下面咱們來看一下具體的配置代碼


  • web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <!--
        下面的代碼是選擇Spring配置文件的路徑,也能夠定義Spring配置文件的名字
        若是不配置Spring默認在項目根目錄下查找applicationContext.xml文件
    -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <!--
            若是配置多個文件能夠用逗號分隔,也能夠用資源前綴的方式配置
            ? : 匹配文件名中的一個字符
            * : 匹配文件名中的任意個字符
           ** : 匹配多層路徑
           classpath:com/t?st.xml 匹配com類路徑下的com/tast.xml、tbst.xml 等
           classpath:com/*.xml 匹配com類路徑下的全部xml文件
           classpath:com/**.xml 匹配com類路徑及其子目錄下的全部xml文件
        -->
        <param-value>classpath:beans.xml</param-value>
    </context-param>
    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

</web-app>

  • 在SpringIoC容器中一個Bean對應配置文件中的一個<bean>,id爲這個Bean的名稱,經過容器的getBean()方法獲取對應的Bean。id在IoC容器中必須是惟一的,它的命名還要知足XML對id的命名規範:必須以字母開始,後機能夠是字母、數字、連字符、下劃線、等。可是,在特殊狀況下,咱們須要特別的名字,那id就不容許了。這時咱們能夠用name屬性。name屬性沒有字符限制,幾乎可使用任何字符,並能夠設置多個名字。以下所示

<bean name="#1, $2" class="com.xiaobai.spring.mark.Car" p:brand="衆泰T600S" p:color="白色" p:speed="120"/>
  • Spring配置文件雖然不容許出現兩個id的<bean>,但卻能夠出現兩個name的<bean> 若是有多個name相同的<bean> 獲取時,將返回最後聲明的那個Bean,緣由是後面的<bean>覆蓋了前面的<bean>.若是id和name兩個屬性都未指定,Spring自動將class作爲Bean的名稱。以下所示

<bean class="com.xiaobai.spring.mark.Car" p:brand="衆泰T600S" p:color="白色" p:speed="120"/>
@Test
public void applicationContextCreateCar() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:xiaobai/beans.xml");
    Car car = applicationContext.getBean("com.xiaobai.spring.mark.Car", Car.class);
    System.out.println(car);
}
  • 執行結果

Car{brand='衆泰T600S', color='白色', speed=120}
相關文章
相關標籤/搜索