Java框架之Spring 01-IOC-bean配置-文件引入-註解裝配

Spring

 框架,即framework。是對特定應用領域中的應用系統的部分設計和實現的整體結構。就相當於讓別人幫你完成一些基礎工作,它可以處理系統很多細節問題,而且框架一般是成熟,穩健的。

 Spring概述

   Spring是一個IOC(DI)和AOP容器框架

   Spring的優良特性

     ①   非侵入式:基於Spring開發的應用中的對象可以不依賴於Spring的API

     ②   依賴注入:DI——Dependency Injection,反轉控制(IOC)最經典的實現。

     ③   面向切面編程:Aspect Oriented Programming——AOP

     ④   容器:Spring是一個容器,因爲它包含並且管理應用對象的生命週期

     ⑤   組件化:Spring實現了使用簡單的組件配置組合成一個複雜的應用。在 Spring 中可以使用XML和Java註解組合這些對象。

     ⑥  一站式:在IOC和AOP的基礎上可以整合各種企業應用的開源框架和優秀的第三方類庫(實際上Spring 自身也提供了表述層的SpringMVC和持久層的Spring JDBC)。

 Spring模塊

 IOC和DI

 IOC(Inversion of Control):反轉控制

   反轉了資源的獲取方向——改由容器主動的將資源推送給需要的組件,開發人員不需要知道容器是如何創建資源對象的,只需要提供接收資源的方式即可。這種行爲也稱爲查找的被動形式。

 DI(Dependency Injection):依賴注入

   即組件以一些預先定義好的方式(例如:setter 方法)接受來自於容器的資源注入。

   總結: IOC 就是一種反轉控制的思想, 而DI是對IOC的一種具體實現。

IOC容器在Spring中的實現

  導入Spring框架jar包

  創建配置文件,常用文件名:applicationContext.xml或beans.xml

  • Spring中有IOC思想,  IOC思想必須基於 IOC容器來完成, 而IOC容器在最底層實質上就是一個對象工廠

    1)在通過IOC容器讀取Bean的實例之前,需要先將IOC容器本身實例化

    2)Spring提供了IOC容器的兩種實現方式

  ① BeanFactory:IOC容器的基本實現,是Spring內部的基礎設施,是面向Spring本身的,不是提供給開發人員使用的。

  ② ApplicationContext:BeanFactory的子接口,提供了更多高級特性。面向Spring的使用者,幾乎所有場合都使用ApplicationContext而不是底層的BeanFactory。

ApplicationContext的主要實現類

  ClassPathXmlApplicationContext:對應類路徑下的XML格式的配置文件

  FileSystemXmlApplicationContext:對應文件系統中的XML格式的配置文件

  在初始化時就創建單例的bean,也可以通過配置的方式指定創建的Bean是多實例的。

ConfigurableApplicationContext

      是ApplicationContext的子接口,包含一些擴展方法

      refresh()和close()讓ApplicationContext具有啓動、關閉和刷新上下文的能力。所以要關閉ApplicationContext需要new此接口的對象調用close()方法

WebApplicationContext

       專門爲WEB應用而準備的,它允許從相對於WEB根目錄的路徑中完成初始化工作

  從IOC容器中獲取bean,推薦同時指定bean的id值和類型

//通過在XML文件中配置的id及class類型獲取對象
HelloWorld helloWorld = cxt.getBean("helloWorld",HelloWorld.class);

bean標籤

  bean標籤:將bean裝配到springIOC容器中 
  bean標籤中屬性
     id:對象唯一標識(可以不寫,如果書寫必須是唯一值)
       class:裝配bean的全類名

  bean子標籤

    property:爲對象中的屬性賦值
      name:屬性名
      value:屬性值

    constructor-arg:通過構造器賦值 

給bean的屬性賦值

1. 通過bean的setXxx()方法賦值

2. 通過bean的構造器賦值,注意:如果構造器中參數類型兼容,可能出現錯誤賦值情況。

<bean id="student" class="com.bean.Student01">
        <property name="name" value="小明"></property>
        <constructor-arg name="age" value="18"></constructor-arg>
</bean>

3. p名稱空間

<bean id="student" class="com.bean.Student01"
        p:name="小明" 
        p:age="18">
</bean>

屬性可使用的值

1. 字面量

      基本數據類型及其封裝類、String等類型都可以採取字面值注入的方式

      若字面值中包含特殊字符,可以使用<![CDATA[]]>把字面值包裹起來或轉義字符

2. null值

<property name= "bookName">
         <null/>
</property>

3. 給bean的級聯屬性賦值

  設置級聯屬性後會修改原屬性值,一般不使用

4. 外部已聲明的bean、引用其他的bean:此時value已經滿足不了需求了要用ref屬性

<bean id="school" class="com.bean.School">
        <property name="stus" ref="stu"></property>
</bean>

5. 內部bean

  當bean實例僅僅給一個特定的屬性使用時,可以將其聲明爲內部bean。內部bean聲明直接包含在<property>或<constructor-arg>元素裏,不需要設置任何id或name屬性

  內部bean不能使用在任何其他地方,即不能在容器中直接獲取內部bean

爲bean注入集合屬性

數組和List

  需要指定<list>標籤,在標籤裏包含一些元素。這些標籤可以通過<value>指定簡單的常量值,通過<ref>指定對其他Bean的引用。通過<bean>指定內置bean。通過<null/>指定空元素。甚至可以內嵌其他集合。

  數組的定義和List一樣,都使用<list>元素。

  配置java.util.Set需要使用<set>標籤,定義的方法與List一樣。

<bean id="shop" class="com.spring.bean.Shop" >
      <property name= "bookList">
           <!-- 以bean的引用爲值的List集合 -->
           <list>
               <ref bean= "book01"/>
               <ref bean= "book02"/>
           </list>
       </property>
</bean >

Map

  通過<map>標籤定義,<map>標籤裏可以使用多個<entry>作爲子標籤。每個條目包含一個鍵和一個值。

        必須在<key>標籤裏定義鍵,因爲鍵和值的類型沒有限制,所以可以自由地爲它們指定<value>、<ref>、<bean>或<null/>元素。

<bean id="cup" class="com.spring.bean.Cup">
    <property name="bookMap">
        <map>
           <entry key="book" value-ref="bookMap"></entry>
             <entry>
                  <key>
                      <value>bookKey01</value>
                  </key>
                  <ref bean="book01"/>
              </entry>
        </map>
    </property>
</bean>                

集合類型的bean

  將集合bean的配置提取到外面,可供其他bean引用,實現重用

 <util:list id="schoolList">
        <ref bean="stu"></ref>
</util:list>

FactoryBean

  如果需要程序員參與創建bean的過程之中,使用FactoryBean

  工廠bean跟普通bean不同,其返回的對象不是指定類的一個實例,其返回的是該工廠bean的getObject方法所返回的對象。

  工廠bean必須實現org.springframework.beans.factory.FactoryBean接口,並重寫3個方法

<bean id="schoolFactory" class="com.factoryBeanImpl.SchoolFactory">
</bean>

bean的作用域

  可以在<bean>元素的scope屬性裏設置bean的作用域,以決定這個bean是單實例的還是多實例的。

  singleton,是所有bean的默認作用域。注意:工廠bean是通過isSingleton()方法設置是否單例的

  當bean的作用域爲單例時,Spring會在IOC容器對象創建時就創建bean的對象實例

  而當bean的作用域爲prototype時,IOC容器在獲取bean的實例時創建bean的實例對象

bean的生命週期

      在配置bean時,通過init-method和destroy-method 屬性爲bean指定初始化和銷燬方法

      Spring IOC容器對bean的生命週期進行管理的過程:

         ① 通過構造器或工廠方法創建bean實例

         ② 爲bean的屬性設置值和對其他bean的引用

         ③ 調用bean的初始化方法

         ④  bean可以使用了

         ⑤ 當容器關閉時,調用bean的銷燬方法

<bean id="stu" class="com.bean.Student" init-method="init" destroy-method="destroy">
</bean>

   bean的後置處理器

     ① bean後置處理器允許在調用初始化方法前後對bean進行額外的處理

               ② bean後置處理器對IOC容器裏的所有bean實例逐一處理,而非單一實例。

     ③ bean後置處理器需要實現接口:org.springframework.beans.factory.config.BeanPostProcessor。

      在初始化方法被調用前後,Spring將把每個bean實例分別傳遞給上述接口的以下兩個方法:

      ●postProcessBeforeInitialization(Object bean, String beanId):初始化之前執行

      ●postProcessAfterInitialization(Object, String):初始化之後執行

   注意

     參數bean:IOC容器中創建的對象

     參數beanId:IOC容器中創建對象的beanId

引用外部文件

  將一部分信息提取到bean配置文件的外部,以properties格式的屬性文件保存起來,同時在bean的配置文件中引用properties屬性文件中的內容,從而實現一部分屬性值在發生變化時僅修改properties屬性文件即可。

1. 創建properties屬性文件

jdbc.username=root
jdbc.password=12345
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test

2. 引入context名稱空間

3.指定properties屬性文件的位置

<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>

classpath: 引入當前項目中類路徑下的資源文件
classpath*: 引入所項目中類路徑下的資源文件

4.從properties屬性文件中引入屬性值

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
        p:username="${jdbc.username}"
        p:password="${jdbc.password}"
        p:driverClassName="${jdbc.driverClass}"
        p:url="${jdbc.url}">
</bean>

自動裝配

      手動裝配:在XML配置文件中以value或ref的方式明確指定屬性值都是手動裝配。

      自動裝配:根據指定的裝配規則,不需要明確指定,Spring容器會自動將匹配的屬性值注入bean中。

      注意:自動裝配屬性的數據類型,只能是[非字面量]值。[字面量]值不能自動裝配。即基本數據類型(包裝類)+String類型都不可自動裝配

 裝配方式

  1.  根據類型自動裝配:將類型匹配的bean作爲屬性注入到另一個bean中。當有多個與目標bean類型一致將報錯
  2.  根據名稱自動裝配:必須將目標bean的名稱和屬性名設置的完全相同
  3. 通過構造器自動裝配:當bean中存在多個構造器時,此種自動裝配方式將會很複雜。不推薦使用。

 基於xml,自動裝配(不推薦)

   在bean中添加autowire="byName|byType"

<bean id="student" class="com.springdemo.autowired.Student" autowire="byType"></bean>

  byName:通過類中的屬性名與bean中id(IOC容器中的id匹配)。
  * 如果數值一致,匹配成功。 如果不一致,裝配失敗(不會報錯,裝配null值)

  byType:通過類中的屬性類型與bean中的class匹配
  * 如果一致,匹配成功。
  * 如果未找到匹配類型,裝配失敗(裝配null值)
  * 如果匹配到多個兼容類型(父子關係:裝配失敗,結果會報錯)

 基於註解,自動裝配bean

   需在XML文檔中先添加掃描組件標籤,指定需被裝配bean的package

<context:component-scan base-package="com.bookStore" use-default-filters="true"></context:component-scan>

 

  base-package:Spring容器會掃描這個基類包及其子包中的所有類。當需要掃描多個包時可以使用逗號分隔。

  如果僅希望掃描特定的類而非基包下的所有類,可使用resource-pattern屬性過濾特定的類

  use-default-filters="true":默認組件掃描(掃描當前base-package下的包及其子包),false:不掃描...

通過子標籤控制包含與排除

  <context:include-filter>包含掃描,掃描指定匹配規則下的包及其子包

    注意:通過將use-default-filters屬性設置爲false,禁用默認過濾器,然後掃描的就只是include-filter中的規則指定組件了    

  <context:exclude-filter>排除掃描,子節點表示要排除在外的目標類

    注意:將use-default-filters屬性設置爲true或默認

過濾表達式,指定類型

類別

示例

說明

annotation

com.XxxAnnotation

過濾所有標註了XxxAnnotation的類。這個規則根據目標組件是否標註了指定類型的註解進行過濾。

assignable

com.BaseXxx

過濾所有BaseXxx類的子類。這個規則根據目標組件是否是指定類型的子類的方式進行過濾。

aspectj

com.*Service+

所有類名是以Service結束的,或這樣的類的子類。這個規則根據AspectJ表達式進行過濾。

regex

com\.anno\.*

所有com.anno包下的類。這個規則根據正則表達式匹配到的類名進行過濾。

custom

com.XxxTypeFilter

使用XxxTypeFilter類通過編碼的方式自定義過濾規則。該類必須實現org.springframework.core.type.filter.TypeFilter接口

 

4個註解:

  1) 普通組件:@Component

  2) 表述層控制器組件:@Controller

  3) 業務邏輯層組件:@Service

  4) 持久化層組件:@Repository

  組件命名規則

         ①默認情況:使用組件的簡單類名首字母小寫作爲bean的id

    ②使用組件註解的value屬性指定bean的id:  @Component(value="指定id名")

自動裝配bean中的屬性

實現原理

  在指定要掃描的包時,<context:component-scan> 元素會自動註冊一個bean的後置處 理器:AutowiredAnnotationBeanPostProcessor的實例。該後置處理器可以自動裝配標記 了@Autowired、@Resource或@Inject註解的屬性。

@Autowired

  注入方式:既不是set注入,也不是構造注入。本質:是通過反射注入。

  自動裝配規則 

    優先使用byType進行裝配,如果能唯一匹配,則裝配成功。
    如果匹配到多個兼容類型的bean,再照byName方式匹配(進行唯一篩選)
    如果通過byName唯一確定bean,則裝配成功,否則裝配失敗。

  構造器、普通字段(即使是非public)、一切具有參數的方法都可以使用@Autowired註解

  若某一屬性允許不被裝配,可以設置@Autowired註解的required屬性爲 false

    required:默認值是true,必須裝配該bean

    required值爲false時,如果IOC容器中存在該bean,則裝配。如果沒有,則不裝配。

  @Autowired註解也可以應用在數組類型的屬性上

  @Autowired註解也可以應用在集合屬性上,此時Spring讀取該集合的類型信息,然後自動裝配所有與之兼容的bean。

  @Autowired註解用在java.util.Map上時,若該Map的鍵值爲String,那麼 Spring將自動裝配與值類型兼容的bean作爲值,並以bean的id值作爲鍵。

@Qualifier

  必要時,可以組合使用@Qualifier(value="userDaoMyBatisImpl")註解指定beanId名

  Spring甚至允許在方法形參上標註@Qualifiter註解以指定注入bean的名稱。

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