(最近在看spring,看到黑馬視訊教程裡面有些東西寫的還不錯,就稍微整合了一些,跟大家分享一下! )
Spring作為一個在java界廣泛使用且評價頗高的一個開源架構,給我們提供了好多的功能,極大的友善了我們的開發。此處将介紹IOC容器和AOP概念。
IOC(Inversion of Control)控制反轉:本來是由應用程式管理的對象之間的依賴關系,現在交給了容器管理,這就叫控制反轉,即交給了IOC容器,Spring的IOC容器主要使用DI方式實作的。不需要主動查找,對象的查找、定位和建立全部由容器管理。
通俗點說就是不建立對象。以前我們要調用一個對象的方法,首先要new一個對象。但使用IOC容器,在代碼中不直接與對象連接配接,而是在配置檔案中描述要使用哪一個對象。容器負責将這些聯系在一起。
IOC容器的對象執行個體化是通過配置檔案來實作的。術語上這叫做注入。注入有兩種形式,采用構造方法注入和采用setter注入。具體的注入形式如下
1.采用set方法注入
給屬性添加一個set方法,并對其進行指派
publicclass UserManagerImplimplements UserManager {
private UserDaouserDao;
publicvoid setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
配置檔案:
<beanid="userManager"class="com.bjpowernode.spring.manager.UserManagerImpl">
<property name="userDao" ref="usrDao4Oracle"/>
</bean>
set注入特點:
與傳統的JavaBean的寫法更相似,程式員更容易了解、接受,通過setter方式設定依賴關系顯得更加直覺、明顯;
對于複雜的依賴關系,如果采用構造注入,會導緻構造器過于臃腫,難以閱讀。Spring在建立Bean執行個體時,需要同時執行個體化其依賴的全部執行個體,因而導緻死你功能下降。而使用設定注入,則避免這下問題;
尤其在某些屬性可選的情況下,多參數的構造器更加笨拙。
2.采用構造方法注入,在構造方法中對屬性進行指派
publicclass UserManagerImplimplements UserManager {
private UserDaouserDao;
public UserManagerImpl(UserDao userDao) {
this.userDao = userDao;
}
}
配置檔案:
<beanid="userManager"class="com.bjpowernode.spring.manager.UserManagerImpl">
<constructor-arg ref="userDao4Mysql"/>
</bean>
構造方法注入特點:
構造注入可以在構造器中決定依賴關系的注入順序,優先依賴的優先注入。
<p LINE-HEIGHT= 25px" align="left"> 對于依賴關系無須變化的Bean,構造注入更有用處;因為沒有setter方法,所有的依賴關系全部在構造器内設定,是以,不用擔心後續代碼對依賴關系的破壞。
依賴關系隻能在構造器中設定,則隻有元件的建立者才能改變元件的依賴關系。對元件的調用者而言,元件内部的依賴關系完全透明,更符合高内聚的原則;
建議采用以設定注入為主,構造注入為輔的注入政策。對于依賴關系無須變化的注入,盡量采用構造注入;而其他的依賴關系的注入,則考慮采用設定注入。
此處我們說的普通屬性的注入,但是還有一些清單,數組,map等類型的變量。
我們看一下他們的注入形式:
<bean id="bean1" class="com.bjpowernode.spring.Bean1">
<property name="strValue" value="Hello_Spring"/>
<!--
<property name="intValue" value="123"/>
-->
<property name="intValue">
<value>123</value>
</property>
<property name="listValue">
<list>
<value>list1</value>
<value>list2</value>
</list>
</property>
<property name="setValue">
<set>
<value>set1</value>
<value>set2</value>
</set>
</property>
<property name="arrayValue">
<list>
<value>array1</value>
<value>array2</value>
</list>
</property>
<property name="mapValue">
<map>
<entry key="k1" value="v1"/>
<entry key="k2" value="v2"/>
</map>
</property>
<property name="dateValue" value="2009年12月14日" />
</bean>
spring中并不是所有類型的編輯器都實作好了,有些類型比如時間他就沒有實作。需要我們自己去定義。如何自定義屬性編輯器呢?首先,要繼承 PropertyEditorSupport類,然後覆寫setAsText()方法,最後将自定義的屬性編輯器注入到spring中
public class UtilDatePropertyEditorextends PropertyEditorSupport {
private Stringpattern;
@Override
publicvoid setAsText(String text)throws IllegalArgumentException {
System.out.println("---UtilDatePropertyEditor.setAsText()--->" + text);
try {
Date date = new SimpleDateFormat(pattern).parse(text);
this.setValue(date);
} catch (ParseException e) {
e.printStackTrace();
thrownew IllegalArgumentException(text);
}
}
publicvoid setPattern(String pattern) {
this.pattern = pattern;
}
}
這裡pattern比對形式,我們采用的是set注入。配置檔案中實作為:
<bean id="customEditors" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.util.Date">
<bean class="com.bjpowernode.spring.UtilDatePropertyEditor">
<property name="pattern" value="yyyy年MM月dd日"/>
</bean>
</entry>
</map>
</property>
</bean>
從上面可以看出,配置檔案中每一個類用bean标簽來辨別,屬性用property來辨別。如果屬性多的話,配置檔案也會很繁雜。有沒有某種情況能夠減少配置檔案的一些設定呢?确實是可以的,如果幾個bean都有相同的屬性,那這些屬性是可以抽象出來的。比如:
<bean id="AbstractBean"abstract="true">
<propertyname="id"value="100"/>
<propertyname="name"value="zhangsan"/>
<propertyname="sex"value="nan"/>
</bean>
<beanid="bean3"class="com.bjpowernode.spring.Bean3"parent="AbstractBean"/>
<beanid="bean4"class="com.bjpowernode.spring.Bean4"parent="AbstractBean">
<propertyname="age">
<value>90</value>
</property>
</bean>
bean3,bean4中有相同的屬性,id,name,sex,則可以将其抽象出一個抽象bean,然後,在具體bean中指定其parent标簽為抽象bean。
我們都知道正規表達式,用一個統一的格式表示多種不同的字元。在IOC中也有類似的功能。有得時候某個對象中包含其他對象的屬性。如果,這些屬性名稱 name間或者類型(具體的包名類名)有某種關系的話,是可以不用顯示調用的。IOC容器自動就回去查找。如:
<beans ...
default-autowire="byName"
>
<!--
<bean id="bean2" class="com.bjpowernode.spring.Bean2">
<property name="bean3" ref="bean3"/>
<property name="bean4">
<ref bean="bean4"/>
</property>
<property name="bean5" ref="bean5"/>
</bean>
-->
<bean id="bean2" class="com.bjpowernode.spring.Bean2"/>
<beans ...
default-autowire="byType"
>
<!--
<bean id="bean2" class="com.bjpowernode.spring.Bean2">
<property name="bean3" ref="bean3"/>
<property name="bean4">
<ref bean="bean4"/>
</property>
<property name="bean5" ref="bean5"/>
</bean>
-->
<bean id="bean2" class="com.bjpowernode.spring.Bean2"/>
<bean id="bean322" class="com.bjpowernode.spring.Bean3">
<property name="id" value="100"/>
<property name="name" value="zhangsan"/>
<property name="sex" value="nan"/>
</bean>
IOC容器實作的bean配置與我們在代碼中new執行個體達到的效果是一樣的。那我們執行個體化的時候,可以采用單例模式,隻保證有一個執行個體在運作,也可以多個執行個體運作。IOC容器中有這種配置嗎?當然有,那就是bean的scope作用域。singleton預設值,每次調用getBean()向IOC容器中取得的對象是相同的。即單例。而prototype,則是每次調用getBean()向IOC容器中取得對象是不相同的。即相當于普通的執行個體化。
<bean id="bean1"class="com.bjpowernode.spring.Bean1"scope="prototype"/>
或者
<bean id="bean1"class="com.bjpowernode.spring.Bean1"scope="singleton"/>
通過IOC控制反轉,大量減少了Factory和Singleton的數量,使代碼層次更加清晰。Spring的IOC容器是一:個輕量級的容器,沒有侵入性,不需要依賴容器的API,也不需要實作一些特殊接口。而一個合理的設計最好盡量避免侵入性。減少了代碼中的耦合,将耦合推遲到了配置檔案中,發生了變化也更容易控制。
AOP(aspect object programming)就是面向切面程式設計
AOP的功能就是讓關注點代碼與業務代碼分離!
了解AOP需要清楚一些概念:
關注點:
重複代碼就叫做關注點;
切面:
關注點形成的類,就叫切面(類)!
面向切面程式設計,就是指 對很多功能都有的重複的代碼抽取,再在運作的時候往業務方法上動态植入“切面類代碼”。
切入點:
執行目标對象方法,動态植入切面代碼。
可以通過切入點表達式,指定攔截哪些類的哪些方法; 給指定的類在運作的時候植入切面類代碼。
切入點表達式:
可以對指定的“方法”進行攔截,進而給指定的方法所在的類生層代理對象。