Spring學習之IOC

 

配置 bean

配置形式:基於 XML 文件的方式;基於註解的方式

Bean 的配置方式:通過全類名(反射)、通過工廠方法(靜態工廠方法 & 實例工廠方法)、FactoryBean

IOC 容器 BeanFactory & ApplicationContext概述

依賴注入的方式:屬性注入;構造器注入

自動轉配 :    auto屬性,會自動給剩下的所有屬性賦值

bean 之間的關係:parent和depends-on

bean 的作用域:singleton;prototype;WEB 環境作用域

使用外部屬性文件

spEL

IOC 容器中 Bean 的生命週期

Spring 4.x 新特性:泛型依賴注入

 

 

IOC(Inversion of Control):其思想是反轉資源獲取的方向. 傳統的資源查找方式要求組件向容器發起請求查找資源. 作爲迴應, 容器適時的返回資源. 而應用了IOC 之後, 則是容器主動地將資源推送給它所管理的組件, 組件所要做的僅是選擇一種合適的方式來接受資源. 這種行爲也被稱爲查找的被動形式

 

 <?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:util="http://www.springframework.org/schema/util"
 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
  http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
 
 <!-- 配置一個 bean 一個bean標籤代表給容器添加了一個對象.class用全類名錶示通過反射方式實例化對象,所以類中需要一個無參的構造函數,-->
 <bean id="helloWorld" class="com.atguigu.spring.helloworld.HelloWorld">
  <!-- 爲屬性賦值 -->
  <property name="user" value="Jerry"></property>
 </bean>
 
 <!-- 配置一個 bean -->
 <bean id="helloWorld2" class="com.atguigu.spring.helloworld.HelloWorld">
  <!-- 爲屬性賦值 -->
  <!-- 通過屬性注入: 通過 setter 方法注入屬性值 -->
  <property name="user" value="Tom"></property>
 </bean>
 
 <!-- 通過構造器注入屬性值 -->
 <bean id="helloWorld3" class="com.atguigu.spring.helloworld.HelloWorld">
  <!-- 要求: 在 Bean 中必須有對應的構造器.  -->
  <constructor-arg value="Mike"></constructor-arg>
 </bean>
 
 <!-- 若一個 bean 有多個構造器, 如何通過構造器來爲 bean 的屬性賦值 -->
 <!-- 可以根據 index 和 value 進行更加精確的定位. (瞭解) -->
 <bean id="car" class="com.atguigu.spring.helloworld.Car">
  <constructor-arg value="KUGA" index="1"></constructor-arg>
  <constructor-arg value="ChangAnFord" index="0"></constructor-arg>
  <constructor-arg value="250000" type="float"></constructor-arg>
 </bean>
 
 <bean id="car2" class="com.atguigu.spring.helloworld.Car">
  <constructor-arg value="ChangAnMazda"></constructor-arg>
  <!-- 若字面值中包含特殊字符, 則可以使用 CDATA 來進行賦值. (瞭解) -->
  <constructor-arg>
   <value><![CDATA[<ATARZA>]]></value>
  </constructor-arg>
  <constructor-arg value="180" type="int"></constructor-arg>
 </bean>
 
 <!-- 配置 bean -->
 <bean id="dao5" class="com.atguigu.spring.ref.Dao"></bean>
 <bean id="service" class="com.atguigu.spring.ref.Service">
  <!-- 引用類型用ref -->
  <property name="dao" ref="dao5"></property>
 </bean>
 
 <!-- 用bean標籤來配置內部bean -->
 <bean id="service2" class="com.atguigu.spring.ref.Service">
  <property name="dao">
   <!-- 內部 bean, 類似於匿名內部類對象. 不能被外部的 bean 來引用, 也沒有必要設置 id 屬性 -->
   <bean class="com.atguigu.spring.ref.Dao">
    <property name="dataSource" value="c3p0"></property>
   </bean>
  </property>
 </bean>
 
 <bean id="action" class="com.atguigu.spring.ref.Action">
  <property name="service" ref="service2"></property>
  <!-- 設置級聯屬性(瞭解) -->
  <property name="service.dao.dataSource" value="DBCP2"></property>
 </bean>
 
 <bean id="dao2" class="com.atguigu.spring.ref.Dao">
  <!-- 爲 Dao 的 dataSource 屬性賦值爲 null, 若某一個 bean 的屬性值不是 null, 使用時需要爲其設置爲 null(瞭解) -->
  <property name="dataSource"><null/></property>
 </bean>
 
 <!-- 裝配集合屬性 -->
 <bean id="user" class="com.atguigu.spring.helloworld.User">
  <property name="userName" value="Jack"></property>
  <property name="cars">
   <!-- 集合屬性就用個list標籤 -->
   <list>
    <ref bean="car"/>
    <ref bean="car2"/>
   </list>
  </property>
 </bean>
 
 <!-- 用util命名空間將一個集合作爲一個工具,其他類可以指向它 -->
 <util:list id="cars">
  <ref bean="car"/>
  <ref bean="car2"/>
 </util:list>
 
 <bean id="user2" class="com.atguigu.spring.helloworld.User">
  <property name="userName" value="Rose"></property>
  <!-- 引用外部聲明的 list -->
  <property name="cars" ref="cars"></property>
 </bean>
 <!--使用p命名空間,能簡化書寫-->
 <bean id="user3" class="com.atguigu.spring.helloworld.User"
  p:cars-ref="cars" p:userName="Titannic"></bean>
  
 <!-- 用parent可以在配置文件中繼承配置 --> 
 <bean id="user4" parent="user" p:userName="Bob"></bean>
 
 <bean id="user6" parent="user" p:userName="維多利亞"></bean>
 
 <!--depends-on,那麼創建這個對象之前必須先創建好depengs-on的對象 --> 
 <bean id="user5" parent="user" p:userName="Backham" depends-on="user6"></bean>
 
</beans>

 <!-- 自動裝配: 只聲明 bean, 而把 bean 之間的關係交給 IOC 容器來完成 -->
 <!--  
  byType: 根據類型進行自動裝配. 但要求 IOC 容器中只有一個類型對應的 bean, 若有多個則無法完成自動裝配.
  byName: 若屬性名和某一個 bean 的 id 名一致, 即可完成自動裝配. 若沒有 id 一致的, 則無法完成自動裝配
 -->
 <!-- 在使用 XML 配置時, 自動轉配用的不多. 但在基於 註解 的配置時, 自動裝配使用的較多.  -->
 <bean id="dao" class="com.atguigu.spring.ref.Dao">
  <property name="dataSource" value="C3P0"></property>    
 </bean>
 
 <!-- 默認情況下 bean 是單例的! -->
 <!-- 但有的時候, bean 就不能使單例的. 例如: Struts2 的 Action 就不是單例的! 可以通過 scope 屬性來指定 bean 的作用域 -->
 <!--  
  prototype: 原型的. 每次調用 getBean 方法都會返回一個新的 bean. 且在第一次調用 getBean 方法時才創建實例
  singleton: 單例的. 每次調用 getBean 方法都會返回同一個 bean. 且在 IOC 容器初始化時即創建 bean 的實例. 默認值 
 -->
 <bean id="dao2" class="com.atguigu.spring.ref.Dao" scope="prototype"></bean>
 
 <bean id="service" class="com.atguigu.spring.ref.Service" autowire="byName"></bean>
 
 <bean id="action" class="com.atguigu.spring.ref.Action" autowire="byType"></bean>
 
 <!-- 因爲有些對象的屬性是需要改變的,爲了維護的方便,將配置信息寫在外部的資源文件當中
      導入classpath下名字叫db.properties的資源文件 -->
 <context:property-placeholder location="classpath:db.properties"/>
 
 <!-- 配置數據源 用${配置文件中的屬性名}引入-->
 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  <property name="user" value="${jdbc.user}"></property>
  <property name="password" value="${jdbc.password}"></property>
  <property name="driverClass" value="${jdbc.driverClass}"></property>
  <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
  
  <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
  <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
 </bean>
 
 <!--spring表達式語言SpEL:使用 #{…} 作爲定界符,所有在大框號中的字符都將被認爲是 SpEL
 可以爲屬性進行動態的賦值,
 調用靜態方法或靜態屬性:通過 T() 調用一個類的靜態方法,它將返回一個 Class Object,
 然後 再調用相應的方法或屬性
 支持運算符
 引用bean,和bean的屬性和方法 -->
 <bean id="girl" class="com.atguigu.spring.helloworld.User">
  <property name="userName" value="周迅"></property>
 </bean>
 
 <bean id="boy" class="com.atguigu.spring.helloworld.User" init-method="init" destroy-method="destroy">
  <property name="userName" value="#{T(java.lang.MATH).PI*20}"></property>
  <property name="userName" value="高勝遠"></property>
  <property name="wifeName" value="#{girl.userName}"></property>
 </bean>
 
 <!-- 配置 bean 後置處理器: 不需要配置 id 屬性, IOC 容器會識別到他是一個 bean 後置處理器, 並調用其方法 -->
 <bean class="com.atguigu.spring.ref.MyBeanPostProcessor"></bean>

IOC容器管理bean的生命週期

 Spring IOC 容器可以管理 Bean 的生命週期, Spring 允許在 Bean 生命週期的特定點執行定製的任務.

在 Bean 的聲明裏設置 init-method 和 destroy-method 屬性, 爲 Bean 指定初始化和銷燬方法.  

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

     –通過構造器或工廠方法創建 Bean 實例

     –爲 Bean 的屬性設置值和對其他 Bean 的引用

     –調用 Bean 的初始化方法

     –Bean 可以使用了

     –當容器關閉時, 調用 Bean 的銷燬方法

<!--init()和destory()方法都是類中聲明的-->
<bean id="person" class="com.neusoft.person" p:name="zhangsan" init-method="init"
    destory-method="destory">
</bean>

 

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

Bean 後置處理器對 IOC 容器裏的所有 Bean 實例逐一處理, 而非單一實例. 其典型應用是: 檢查 Bean 屬性的正確性或根據特定的標準更改 Bean 的屬性.

對Bean 後置處理器而言, 需要實現接口BeanPostProcessor. 在初始化方法被調用前後, Spring 將把每個 Bean 實例分別傳遞給上述接口的以下兩個方法:

postProcessBeforeInitialization()方法和 postProcessAfterInitialization()方法

 

通過調用靜態工廠方法和實例工廠方法創建 Bean

 

wKioL1ZWeY_B05HIAALwMqIltxE251.png

wKiom1ZWeUKydlK0AAM3e2EA0Gw489.png

wKioL1ZWebGj25gLAAb2EecCCRQ514.png

 

factorybean的方式配置bean

        有些對象是通過系統給定的factorybean來配置得到的

        繼承factorybean的類通過getobject方法返回一個對象,給放到容器中.

wKiom1ZWaF7BswpCAAN8lhTdGnI138.png

配置文件只需要知道factorybean的類和給類的屬性賦值,然後就會給容器中添加factorybean的getObject()方法返回的對象

wKiom1ZWaGGhD_jAAATNj7k4N44933.png

 

通過註解配置bean

組件掃描(component scanning):  Spring 能夠從 classpath下自動掃描, 偵測和實例化具有特定註解的組件

  

特定組件包括:

–@Component: 基本註解, 標識了一個受 Spring 管理的組件

–@Respository: 標識持久層組件

–@Service: 標識服務層(業務層)組件

–@Controller: 標識表現層組件

對於掃描到的組件, Spring 有默認的命名策略: 使用非限定類名, 第一個字母小寫. 也可以在註解中通過 value 屬性值標識組件的名稱

 <!-- base-package 屬性 Spring 容器將會掃描這個基類包裏及其子包中的所有類. 當需要掃描多個包時, 可以使用逗號分隔 ,resource-pattern 屬性過濾特定的類-->
<context:component-scan base-package="com.test.beans" 
            resourse-pattern="auto/*.class"/>
<!-- [!CDATA[<context:include-filter> 子節點表示要包含的目標類
     <context:exclude-filter> 子節點表示要排除在外的目標類
     <context:component-scan> 下可以擁有若干個 <context:include-filter> 和             <context:exclude-filter> 子節點]]-->

 

使用 @Autowired給屬性註解

通過給屬性加這個註解,spring就會自動給這個屬性賦值. 

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

–默認情況下, 所有使用 @Authwired註解的屬性都需要被設置. 當 Spring 找不到匹配的 Bean 裝配屬性時, 會拋出異常, 若某一屬性允許不被設置, 可以設置 @Authwired註解的 required 屬性爲 false

–默認情況下, 當 IOC 容器裏存在多個類型兼容的 Bean 時, 通過類型的自動裝配將無法工作. 此時可以在 @Qualifier 註解裏提供 Bean 的名稱. Spring 允許對方法的入參標註 @Qualifiter已指定注入 Bean 的名稱

–@Authwired註解也可以應用在數組類型的屬性上, 此時 Spring 將會把所有匹配的 Bean 進行自動裝配.

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

@Authwired註解用在 java.util.Map上時, 若該 Map 的鍵值爲 String, 那麼 Spring 將自動裝配與之 Map 值類型兼容的 Bean, 此時 Bean 的名稱作爲鍵值

 

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