一、思想了解
Spring
能有效地組織J2EE應用各層的對象。不管是控制層的Action對象,還是業務層的Service對象,還是持久層的DAO對象,都可在Spring的
管理下有機地協調、運作。Spring将各層的對象以松耦合的方式組織在一起,Action對象無須關心Service對象的具體實作,Service對
象無須關心持久層對象的具體實作,各層對象的調用完全面向接口。當系統需要重構時,代碼的改寫量将大大減少。
上面所說的一切都得宜于Spring的核心機制,依賴注入。依賴注入讓bean與bean之間以配置檔案組織在一起,而不是以寫死的方式耦合在一起。
依賴注入(Dependency Injection)和控制反轉(Inversion of
Control)是同一個概念。具體含義是:當某個角色(可能是一個Java執行個體,調用者)需要另一個角色(另一個Java執行個體,被調用者)的協助時,在
傳統的程式設計過程中,通常由調用者來建立被調用者的執行個體。但在Spring裡,建立被調用者的工作不再由調用者來完成,是以稱為控制反轉;建立被調用者
執行個體的工作通常由Spring容器來完成,然後注入調用者,是以也稱為依賴注入。
簡而言之:所謂控制反轉就是應用本身不負責依賴對象的建立及維護,依賴對象的建立及維護是由外部容器負責的。這樣控制權就由應用轉移到了外部容器,控制權的轉移就是所謂反轉;所謂依賴注入就是指:在運作期,由外部容器動态地将依賴對象注入到元件中。
不管是依賴注入,還是控制反轉,都說明Spring采用動态、靈活的方式來管理各種對象。對象與對象之間的具體實作互相透明。
關于IOC的學習可以參看幫助文檔:spring-3.2.0.M2\docs\reference\html目錄下index.html的相關章節
二、IOC的相關操作
A、IOC之Bean的執行個體化方式(隻是執行個體化,并沒有初始化)
1)使用類無參構造器執行個體化
<bean id="orderService"
class="cn.itcast.OrderServiceBean"/>
2)使用靜态工廠方法執行個體化
<bean id="personService"
class="cn.itcast.service.OrderFactory"
factory-method="createOrder"/>
public class OrderFactory {
public
static OrderServiceBean createOrder(){
return new
OrderServiceBean();
}
3)通過非靜态工廠方法執行個體化:
<bean id="personServiceFactory"
class="cn.itcast.service.OrderFactory"/>
factory-bean="personServiceFactory"
OrderServiceBean createOrder(){
}
-------------------------------------------------------------
B、IOC之Bean屬性的依賴注入(DI)方式
(即Bean的初始化)
1)setter方法注入
Course類中存在如下setter方法:
public void setId(Intenger
id)
{ this.id = id;}
<bean
id="course" class="com.etc.vo.Course">
<property name="id">
<value>1</value>
</property>
</bean>
2)構造方法注入
public Course (Interge id ,
String title,Double price)
{this.id = id; this.title =
title; this.price = price;}
id="course4" class="com.etc.vo.Course">
<constructor-arg index="0">
<value>4</value>
</constructor-arg>
<constructor-arg index="1">
<value>Java</value>
<constructor-arg index="2">
<value>1000</value>
</bean>
###############:上面兩種方式也可以寫成下面的形式:
id="orderService"
class="cn.itcast.service.OrderServiceBean">
<constructor-arg index="0"
value=“xxx”/>//構造器注入
<property name=“name”
value=“zhao/>//屬性setter方法注入
3)設定注入(使用屬性檔案的)
在項目開發中,有時候要從一些配置檔案中(properties)讀取一些配置資訊,如資料庫的連接配接資訊。在Spring程式中可以從不同的
properties中讀取有用的資訊。這裡要用到
org.springframeword.beans.factory.config.PropertyPlaceholderConfigurer類,它是BeanFactoryPostProcessor的實作類.
下面例子:
項目結構:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-YWan5yNxIWMkFmNxkDMwYGNxIjNzEjZlFWY2MzYlBzMhNWMj9CX0EzLchDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLzM3Lc9CX6MHc0RHaiojIsJye.gif)
connet.properties:
test.properties:
Connect.java裝載着兩個properties的資訊:下面
public class Connect {
private
String driver;
String username;
String password;
int
age;
height;
weight;
//省略getter,setter
beans.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-2.5.xsd">
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property
name="locations">
<list>
<value>connect.properties</value>
<value>test.properties</value>
</list>
<bean id="connect"
class="com.sunflower.yuan.Connect">
<property name="driver">
<value>${driver}</value>
<property name="username">
<value>${username}</value>
<property name="password">
<value>${password}</value>
<property name="age">
<value>${age}</value>
<property name="height">
<value>${height}</value>
<property name="weight">
<value>${weight}</value>
</beans>
C、IOC之針對Bean不同類型屬性的不同注入的配置方式(基于B的依賴注入)
1)屬性類型為8中基本資料類型以及其對應的包裝類和String
<bean id="orderService"
2)屬性為其他Bean類型
public class Order
{private Int id; private Customer
cust;....}
<bean id="custom"
class="cn.itcast.service.CustomBean">
value="zhao"/>//屬性setter方法注入
</bean>
<bean id="order" class="cn.itcast.service.OrderBean">
name=“id” value=1
/>
name=“cust”>
<ref
bean="custom">
3)屬性為null
<property name="name">
<null></null>
</property>
或者:
<property
name="name">
</null>
而不能如下配置(此時該屬性不為null,而是空字元串):
<value></value>
4)屬性為集合類型
public class OrderServiceBean {
Set<String> sets = new
HashSet<String>();
List<String> lists = new
ArrayList<String>();
Properties properties = new Properties();
Map<String, String> maps = new
HashMap<String, String>();
....//這裡省略屬性的getter和setter方法
<bean id="order"
<property name="lists">
<value>pkbest</value>
</property>
<property name="sets">
<set>
</set>
<property name="maps">
<map>
<entry key=“pkbest"
value="28"/>
</map>
<property name="properties">
<props>
<prop
key=“pk">best</prop>
</props>
5)關于使用的注解(Annotation
)方式為屬性提供的依賴注入,請看下篇博文
D、Bean的作用域(基于B的依賴注入)
Bean的作用域共有5種:
single(單例):預設作用域,隻在Spring容器加載時建立唯一的bean執行個體,是以當多次使用getBean方法傳回執行個體,獲得的都是同一個唯一執行個體。如果想對所有bean都應用延遲初始化,可以在根節點beans設定default-lazy-init=“true“,如下:
default-lazy-init="true“
...>
prototype(原型):每次使用該Bean都會建立新的執行個體,我們使用spring管理struts2的action時,所有action的Bean的作用域應該是此類型。
request:表示該針對每一次HTTP請求都會産生一個新的bean,同時該bean僅在目前HTTP
request内有效
session:表示該針對每一次HTTP請求都會産生一個新的bean,同時該bean僅在目前HTTP
session内有效
global
session.不過它僅僅在基于portlet的web應用中才有意義。Portlet規範定義了全局Session的概念,它被所有構成某個portlet
web應用的各種不同的portlet所共享。
以上3種均基于web的Spring ApplicationContext情形下有效
例如:<bean id=“...”
class=“...”
scope=“prototype”/>
E、 Bean的初始化方法和銷毀方法
<bean id="xxx"
class=“biz.OrderServiceBean" init-method="init"
destroy-method="close"/>
public void init() {
System.out.println(“已經初始化了”);
}
public void close() {
System.out.println(“被銷毀了”);
總結:IOC和DI的技術基礎是基于反射技術和JavaBean的自省技術(自省技術的核心是反射技術)