SpringIOC方面知識

1.Spring的框架了解

在這裏插入圖片描述
Spring框架採用的是分層架構,它分爲了20多個模塊,主要有圖上幾個核心模塊。這些模塊大體分爲

1.Core Container(核心容器)模塊:核心容器模塊是其他模塊建立的基礎。有Beans、Core、Context、Context-support模塊和SpEL模塊。
Beans模塊:提供了BeanFactory接口,這個是工廠模式的經典實現,是基礎類型的IOC容器,它是管理Bean的工廠,主要負責初始化各種Bean,然後調用bean的生命週期。BeanFactory是多例對象使用,構建核心容器時,採用延遲加載的方式,但是這種模式在開發中不常用。開發中用它的子接口ApplicationContext來獲取核心容器對象

BeanFactory beanFactory=new XmlBeanFactory(new ClassPathResource("bean.xml"));

Core模塊:是Spring框架的核心工具,Spring其他組件都需要用到這個包裏的類。提供的spring框架基本組成部分,包括IoC和DI功能。

–Context模塊:它是建立在Core和Beans模塊的基礎上,其中包含ApplicationContext接口,被稱爲上下文模塊的焦點。這個ApplicationContext接口是BeanFactory的子接口,一般我們用這種模式來獲取核心容器對象(前提是容器中已經注入bean對象,所以ApplicationContext在初始化時會自檢依賴屬性是否注入)。這種模式適合單例對象,採用立即加載的方式獲得配置bean對象

ApplicationContext的3個常用實現類:

(1)通過ClassPathXmlApplicationContext創建

ClassPathXmlApplicationContext會從類路徑classPath中尋找指定的XML配置文件,找到並裝載完成ApplicationContext的實例化工作,其使用語法如下。

ApplicationContext applicationContext =new ClassPathXmlApplicationContext("bean.xml")

(2).通過FileSystemXmlApplicationContext創建

FileSystemXmlApplicationContext會從指定的文件系統路徑(絕對路徑)中尋找指定的XML配置文件,找到並裝載完成ApplicationContext的實例化工作,其使用語法如下。

ApplicationContext applicationContext =new FileSystemXmlApplicationContext("D:/workspaces/bean.xml")

(3) AnnotationConfigApplicationContext(註解)創建

ApplicationContext applicationContext =new AnnotationConfigApplicationContext(SpringConfiguration.class);

–Context-support模塊:提供第三方庫嵌入Spring的集成支持,比如緩存,郵件發送(JavaMail),任務調度等。

–SpEL模塊:一種表達式語言。

BeanFactory和ApplicationContext區別

BeanFactory和ApplicationContext兩種容器都是通過XML配置文件加載Bean的。二者的主要區別在於,如果Bean的某一個屬性沒有注入,使用BeanFacotry加載後,在第一次調用getBean()方法時會拋出異常,而ApplicationContext則在初始化時自檢,這樣有利於檢查所依賴屬性是否注入。因此,在實際開發中,通常都優先選擇使用ApplicationContext,而只有在系統資源較少時,才考慮使用BeanFactory。

2.Data Access/Integration數據訪問/集成模塊

這裏面常用的模塊有以下3個

–JDBC模塊:提供了一個JDBC的抽象層,大幅度地減少了在開發過程中對數據庫操作的編碼;

–ORM模塊:對流行的對象關係映射API,包括JPA、JDO和Hibernate提供了集成層支持。

–Transactions事務模塊:支持對實現特殊接口以及所有POJO類的編程和聲明式的事務管理。

3.Web:Spring的Web層包括WebSocket、Servlet、Web和Portlet模塊

–Servlet模塊:也稱爲Spring-webmvc模塊,包含了Spring的模型(model)—視圖(view)—控制器(controller)(MVC)和REST Web Services實現的Web應用程序。

–Web模塊:提供了基本的Web開發集成特性,例如:多文件上傳功能、使用Servlet監聽器來初始化IoC容器以及Web應用上下文。

4.AOP(面向切面編程):提供了面向切面編程實現,允許定義方法攔截器和切入點,將代碼按照功能進行分離,以降低耦合性。

5.Instrumentation(工具):提供了類工具的支持和類加載器的實現,可以在特定的應用服務器中使用。

6.Messaging(消息):Spring 4.0以後新增的模塊,它提供了對消息傳遞體系結構和協議的支持。

7.Test(測試):提供了對單元測試和集成測試的支持


2. Spring IOC和依賴注入(DI)

依賴注入(DI)與控制反轉(IOC)的含義相同,只不過從不同的角度來描述同一個概念。

1.IOC:

控制反轉是一種思想。以往某個Java對象(調用者)需要調用另一個java對象時(被調用者,即被依賴對象),調用者通常採用"new 被調用者"的代碼來創建對象,這種方式耦合性太高,還有就是Service底層存在很多構造器,每一次調用都new對象,會太繁瑣。
在這裏插入圖片描述
而在使用Spring框架後,對象的實例不再由調用者來創建,而是由Spring容器來創建。Spring容器會負責控制程序之間的關係,不再是調用者的程序代碼直接控制,它像一個工廠一樣管理很多的bean對象,這樣控制權就由new程序代碼轉移到了Spring容器。

2.依賴注入(DI)

Spring容器負責將被依賴對象(被調用者)賦值給調用者的成員變量,這相當於爲調用者注入了它依賴的實例,這就是Spring的依賴注入。實際就是控制反轉(IOC)思想。
在這裏插入圖片描述

3.Bean的裝配方式/依賴注入 (實例化後,注入Bean中所有屬性值)

Bean的裝配可以理解爲依賴關係注入,Bean的裝配方式即Bean依賴注入的方式。Spring容器支持多種形式的Bean的裝配方式,如基於XML的裝配、基於註解(Annotation)的裝配和自動裝配等(其中最常用的是基於註解的裝配)

3.1 基於XML的裝配(setter和構造方法)

(1) 構造函數注入:這種方式要求待注入的對象中,這個bean類包含有參構造方法,它會調用有參構造方法來注入,而且還要在bean.xml中注入這些參數屬性,否則不注入參數屬性(它就會默認調用無參構造方法,這顯然會報錯)。

在這裏插入圖片描述

//注入有參構造方法的參數屬性
<bean id="accountService" class="com.jh.service.impl.AccountServiceImpl">
        <constructor-arg name="name" value="張三"></constructor-arg>
        <constructor-arg name="age" value="23"></constructor-arg>
        <constructor-arg name="birthday" ref="date"></constructor-arg>
 </bean>
    
    <!--配置一個日期對象-->
    <bean id="date" class="java.util.Date"></bean>      

(2) 以屬性setter方法注入:在Spring實例化Bean的過程中,Spring首先會調用Bean的默認構造方法來實例化Bean對象,然後通過反射的方式調用setter方法來注入屬性值。因此,設值注入要求一個Bean必須滿足以下兩點要求。

· Bean類必須提供一個默認的無參構造方法首先實例化bean(實例化就是創建bean)。

· Bean類必須爲需要注入的屬性提供對應的setter方法。

從settet方法看出依賴注入是在bean實例化之後的

在這裏插入圖片描述

<bean id="accountService2" class="com.jh.service.impl.AccountServiceImpl2">
        <property name="name" value="李四"></property>
        <property name="age" value="21"></property>
        <property name="birthday" ref="date"></property>
    </bean>
   
    <!--配置一個日期對象-->
    <bean id="date" class="java.util.Date"></bean> 

3.2 基於註解(Annotation)的裝配

Spring中定義了一系列的註解,常用的註解如下所示。

  • @Component:可以使用此註解描述Spring中的Bean,但它是一個泛化的概念,僅僅表示一個組件(Bean),並且可以作用在任何層次。使用時只需將該註解標註在相應類上即可。
  • @Repository:用於將數據訪問層(DAO層)的類標識爲Spring中的Bean,其功能與@Component相同
  • @Service:通常作用在業務層(Service層),用於將業務層的類標識爲Spring中的Bean,其功能與@Component相同。
  • @Controller:通常作用在控制層(如Spring MVC的Controller),用於將控制層的類標識爲Spring中的Bean,其功能與@Component相同。
  • @Autowired:用於對Bean的屬性變量、屬性的setter方法及構造方法進行標註,配合對應的註解處理器完成Bean的自動配置工作。默認按照Bean的類型進行裝配。
  • @Resource:其作用與Autowired一樣。其區別在於@Autowired默認按照Bean類型裝配,而@Resource默認按照Bean實例名稱進行裝配。@Resource中有兩個重要屬性:name和type。Spring將name屬性解析爲Bean實例名稱,type屬性解析爲Bean實例類型。如果指定name屬性,則按實例名稱進行裝配;如果指定type屬性,則按Bean類型進行裝配;如果都不指定,則先按Bean實例名稱裝配,如果不能匹配,再按照Bean類型進行裝配;如果都無法匹配,則拋出NoSuchBeanDefinitionException異常。
  • @Qualifier:與@Autowired註解配合使用,會將默認的按Bean類型裝配修改爲按Bean的實例名稱裝配,Bean的實例名稱由@Qualifier註解的參數指定。
  • @Value:以${}注入屬性

3.3 自動裝配(bean.xml中的autowire屬性)

Spring的元素中包含一個autowire屬性,我們可以通過設置autowire的屬性值來自動裝配Bean。所謂自動裝配,就是將一個Bean自動地注入到其他Bean的Property中。
在這裏插入圖片描述
在這裏插入圖片描述
上述配置文件中,用於配置userService和userController的元素中除了id和class屬性外,還增加了autowire屬性,並將其屬性值設置爲byName。在默認情況下,配置文件中需要通過ref來裝配Bean,但設置了autowire="byName"後,Spring會自動尋找userService Bean中的屬性,並將其屬性名稱與配置文件中定義的Bean做匹配。

4.bean的3種實例化方式(實例化就是創建bean對象,默認無參構造器創建)

在面向對象的程序中,我們要使用一個對象及成員屬性,首先得實例化對象,Spring容器也不例外,也需要實例化bean對象,才能使用它,依賴注入都是在bean對象實例化後才能去注入,下面提供三種實例化bean的方式。

//要實例化的bean對象
public class AccountServiceImpl implements IAccountService {
    public AccountServiceImpl(){
        System.out.println("對象創建了");
    }
}

第一種:通過調用無參構造器來實例化bean對象,這也是Spring默認使用的實例化bean的方式,默認調用無參構造方法。

首先定義了配置文件的路徑,然後Spring容器ApplicationContext會加載配置文件。在加載時,Spring容器會通過id爲accountService的實現類AccountServiceImpl中默認的無參構造方法對Bean進行實例化.

//bean.xml
<bean id="accountService" class="com.jh.service.impl.AccountServiceImpl"></bean>

//創建測試類看是否實例化bean
     public static void main(String[] args) {
        //--------ApplicationContext 立即加載----------------------
        //1.獲取核心容器對象
        //ApplicationContext ac= new ClassPathXmlApplicationContext("bean.xml");
        ClassPathXmlApplicationContext ac= new ClassPathXmlApplicationContext("bean.xml");
        //2.根據id獲取Bean對象
        IAccountService as= (IAccountService)ac.getBean("accountService");
        System.out.println(as);//com.jh.service.impl.AccountServiceImpl@1dd92fe2
        as.saveAccount();
        //手動關閉容器
        ac.close();
        }

第二種:通過靜態工廠實例化bean

//bean.xml
<bean id="accountService" class="com.jh.factory.StaticFactory" factory-method="getAccountService"></bean>

/*
使用靜態工廠是實例化Bean的另一種方式。該方式要求開發者創建一個靜態工廠的方法來創建Bean的實例,其Bean配置中的class屬性所指定的不再是Bean實例的實現類,而是靜態工廠類,同時還需要使用factory-method屬性來指定所創建的靜態工廠方法。下面通過一個案例來演示如何使用靜態工廠方式實例化Bean。
*/
public class StaticFactory {
    public static IAccountService getAccountService(){
        //靜態工廠通過返回一個實例對象new AccountServiceImpl()來實例化
        return new AccountServiceImpl();
    }
}

//測試類同上面

第三種:通過普通成員工廠實例化bean

//bean.xml
<bean id="instanceFactory" class="com.jh.factory.InstanceFactory"></bean>
    <bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>

/*
還有一種實例化Bean的方式就是採用實例工廠。此種方式的工廠類中,不再使用靜態方法創建Bean實例,而是採用直接創建Bean實例的方式。同時,在配置文件中,需要實例化的Bean也不是通過class屬性直接指向的實例化類,而是通過factory-bean屬性指向配置的實例工廠,然後使用factory-method屬性確定使用工廠中的哪個方法。下面通過一個案例來演示實例工廠方式的使用。
*/
public class InstanceFactory {
    public IAccountService getAccountService(){
        //也是通過返回一個實例化對象new AccountServiceImpl()來實例化
        return new AccountServiceImpl();
    }
    
//測試同上面

5.bean的作用域和生命週期

1.)5個作用域:img

常用的還是單例singleton、多例prototype。singleton是單例模型:Spring容器創建時,它就會自動調用默認的無參構造器實例化bean(實例化bean就是創建bean對象),不管我們有沒有使用,它都存在,每次獲取的bean對象都是同一個對象,就和對象內存地址一樣的對象。prototype:是多例模型,當創建Spring容器時,並不會立即實例化創建bean對象,而是當需要獲取bean對象時纔去實例化bean,是一種懶漢式,所以它們每一次創建的bean都不是同一個對象。

五種作用域中,request、session和global session三種作用域僅在基於web的應用中使用(不必關心你所採用的是什麼web應用框架),只能用在基於web的Spring ApplicationContext環境。


2)bean的生命週期

Spring容器可以管理singleton(單例模型)作用域的bean的生命週期,在單例模型下能夠精確知道Bean何時被創建,何時被初始化,以及何時被銷燬。
對於prototype作用域的bean,Spring只負責創建bean實例,當容器中有了bean實例後,它的生命週期都交由它的調用者管理,Spring容器不再跟蹤其生命週期,每次調用者請求prototype作用域下的bean時,Spring容器都會創建一個新的實例bean對象,並且不會再管理bean的生命週期。你想一下,每次調用bean都重新創建bean對象,Spring要管理每一個bean生命週期就會很耗費時間,不如交由它的調用者管理。

下面是單例模型下的bean生命週期:
在這裏插入圖片描述
(1)根據配置情況調用Bean構造方法或工廠方法實例化Bean。(2)利用依賴注入完成Bean中所有屬性值的配置注入。

(3)如果Bean實現了BeanNameAware接口,則Spring調用Bean的setBeanName()方法傳入當前Bean的id值。

(4)如果Bean實現了BeanFactoryAware接口,則Spring調用setBeanFactory()方法傳入當前工廠實例的引用。

(5)如果Bean實現了ApplicationContextAware接口,則Spring調用setApplicationContext()方法傳入當前ApplicationContext實例的引用。

(6)如果BeanPostProcessor和Bean關聯,則Spring將調用該接口的預初始化方法postProcessBeforeInitialzation()對Bean進行加工操作,這個非常重要,Spring的AOP就是用它實現的。

(7)如果Bean實現了InitializingBean接口,則Spring將調用afterPropertiesSet()方法。

(8)如果在配置文件中通過init-method屬性指定了初始化方法,則調用該初始化方法。

(9)如果有BeanPostProcessor和Bean關聯,則Spring將調用該接口的初始化方法postProcessAfterInitialization()。此時,Bean已經可以被應用系統使用了。

(10)如果在 中指定了該Bean的作用範圍爲scope=“singleton”,則將該Bean放入Spring IoC的緩存池中,將觸發Spring對該Bean的生命週期管理;如果在中指定了該Bean的作用範圍爲scope=“prototype”,則將該Bean交給調用者,調用者管理該Bean的生命週期,Spring不再管理該Bean。

(11)如果Bean實現了DisposableBean接口,則Spring會調用destory()方法將Spring中的Bean銷燬;如果在配置文件中通過destory-method屬性指定了Bean的銷燬方法,則Spring將調用該方法進行銷燬。

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