Spring的作用:
能夠降低元件之間的耦合度,實作軟體之間的解耦
可以使用Spring容器的衆多服務,比如:事務管理器.當我們使用事務管理器時,開發人員不需要手動控制事務,也不需要處理複雜的事務傳播.
Spring容器提供單例模式的支援
容器提供了AOP技術,利用它很容易實作如權限攔截、運作期監控等.
容器提供了很多輔助器,這些類能夠加快應用的開發,如:JdbcTemplate、HibernateTemplate等.
Spring提供了主流應用架構的支援,如:內建Hibernate、JPA、Struts等,便于應用程式的開發
Spring的核心技術是IoC(Inversion of Control)和AOP(Aspect-oriented programming).
IoC還有另一個名字,叫DI(Dependency Injection),稱為"依賴注入".所謂依賴注入就是指,在運作期間,由外部容器動态地将依賴對象注入到元件中.
依賴注入有三種方式:
使用構造器注入
使用屬性setter注入
使用Field注入(利用注解)
Bean的裝配
Spring提供三種執行個體化Bean的方式:
使用類構造器的方式
<bean id=”唯一辨別符” class=”完整類名”></bean>
使用靜态工廠的方式
<bean id="唯一辨別符" class="工廠的完整類名" factory-method="需要執行工廠的哪個方法的方法名" />
使用工廠執行個體的方式
<bean id=“唯一辨別符1" class="工廠的完整類名"/> <bean id="唯一辨別符2" factory-bean=“唯一辨別符1" factory-method="需要執行工廠的哪個方法的方法名" />
Bean在執行個體化的時候預設隻有一個,不管獲得幾次,都是同一個Bean,不過Spring提供了修改Bean作用域的屬性,有幾種取值:
singleton,prototype,request,session,global session.有幾個都沒什麼用.
除了配置的注入方式以外,還可以使用注解的方式進行注入,在JAVA代碼中使用@Autowired或@Resource注解方式進行裝配.不過在裝配之前,需要引入context命名空間,雖然Spring支援注解的解析,但是預設解析的"開關"沒有打開,必須在配置檔案裡添加<context:annotation-config />标簽,這個标簽隐式的注冊了Spring對注解進行解析的處理器:
AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor,
PersistenceAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor
@Autowired可以作用在構造器、字段和方法上,預設以類型進行查找,預設情況下它要求的依賴對象必須存在,如果可以允許不存在,則需要設定它的required屬性值為false.如果想以名稱進行查找,可以結合@Qualifier注解一起使用,如@Autowired @Qualifier("指定名稱").@Qualifier注解還可以指定在構造器或者方法的參數在,如:
@Autowired public void setPersonDao(@Qualifier("personDao") PersonDao personDao) {//用于屬性的set方法上 this.personDao = personDao; }
@Resource可以作用在類、方法和字段上,預設以名稱進行查找,如果找不到相應的Bean,則以類型進行查找.如果指定了name屬性,則隻按名稱進行查找.
另外,Spring還支援Bean的自動裝配:
<bean id=“foo” class=“...Foo” autowire=“autowire type”>
autowire的取值包含(byType,byName,constructor,autodetecte),隻用了解就行了,不常用,以免出現不可預知的後果.
此外,項目中通常會有上百個元件,如果這些元件全部采用在配置檔案中通過Bean的方式來配置,則會明顯增加配置檔案的體積,查找和維護起來也會相關不便.是以,Spring2.5提供了自動掃描元件的方式來配置元件,它通過在類路徑下尋找标了@Component、@Service、@Controller和@Repository注解的類,并把這些類納入到Spring的容器中進行管理.
要使用自動掃描機制,需要引入context命名空間,并且需要在配置檔案裡面加上:
<context:component-scan base-package="包名"/>.
這個标簽将掃描指定包(含子包)下的所有元件.并且把AutowiredAnnotationBeanPostProcessor 和CommonAnnotationBeanPostProcessor隐式地被包括進來以進行注解解析.
AOP--面向切面程式設計
如果目标對象實作了接口,則代理對象也實作同樣的接口,否則使用cglib代理,則Spring有兩種代理方式:
若目标對象實作了若幹接口,spring使用JDK的java.lang.reflect.Proxy類代理。
若目标對象沒有實作任何接口,spring使用CGLIB庫生成目标對象的子類。
備注:
對接口建立代理優于對類建立代理,因為這将産生更加松耦合的系統.
标記為final的方法無法得到通知,Spring需要為目标類産生子類,需要覆寫被通知的方法,然後将通知織入.final方法不允許被覆寫.
AOP中有幾個概念,這些概念我們經常會用到,大數人也經常在程式中寫出來,但是自己不知道:
連接配接點就是被攔截到的那個點,在Spring中,"點"指的是方法,因為Spring隻支援方法類型的連接配接點.也就是說,哪個方法現在被攔截到了,我們就把這個方法稱為連接配接點.
切入點就是我們要攔截哪些連接配接點.比如你的工作是查水表,你負責的那個區域就是切入點,你現在正在查的那家,就是連接配接點.
通知就是攔截到連接配接點之後要做的事情,比如乘地鐵,你不帶包就不用安檢,如果你帶了包,就要安檢(被攔截到了),然後X射線檢查你的包就是一個通知.通知分為:前置通知,後置通知,最終通知,異常通知,環繞通知五種.
是通知和切入點的結合,通知和切入點共同定義了關于切面的全部内容---它的功能、在何時和何地完成其功能,簡單的說,通知所在的類,并且定義了切入點,那麼這個類就是切面.
需要代理的對象.
把切面應用到目标對象來建立一個代理對象的過程就叫織入.
引入就是在不修改類代碼的前提下, Introduction可以在運作期為類動态地添加一些方法或Field.
要進行AOP程式設計,首先就要引入aop命名空間,Spring提供了兩種切面方式,實際工作中我們可以任選其一:
基于XML配置方式進行AOP開發
基于注解方式進行AOP開發
切面類:
如果使用XML配置方式,需要在檔案中使用<aop:config>标簽,如:
如果想在通知中擷取相關資料,任何通知方法可以将第一個參數定義為<code>org.aspectj.lang.JoinPoint</code>類型 (環繞通知需要定義第一個參數為<code>ProceedingJoinPoint</code>類型, 它是 <code>JoinPoint</code> 的一個子類)。<code>JoinPoint</code> 接口提供了一系列有用的方法,比如 <code>getArgs()</code>(傳回方法參數)、 <code>getThis()</code>(傳回代理對象)、<code>getTarget()</code>(傳回目标)、 <code>getSignature()</code>(傳回正在被通知的方法簽名)和 <code>toString()</code> (列印出正在被通知的方法的有用資訊)。
基于注解的方式除了在配置檔案中引入aop的命名空間以外,還需要打開自動代理:
<aop:aspectj-autoproxy/>
這個标簽将啟用Spring對@AspectJ的支援,配置檔案裡面隻需要聲明切面對象和目标對象就行了,在類上标注@Aspect注解用以聲明切面,然後在切面的方法上面标注通知或者切入點.
定義切入點的幾點注意:
* 切入點使用方法定義的形式出現
* 方法的定義
* 方法的修飾符private修飾
* 方法的傳回值類型是void
* 方法的名稱自定義
* 方法沒有參數
* 方法有方法體,方法體為空
在方法上使用@Pointcut定義切入點,如:
切入點表達式寫法:
* 切入點表達式的寫法
* execution(主要)表示比對方法執行的連接配接點
* 例如: * com.itcast.service..*.save*(..))
* 1 "*" 表示方法的傳回類型任意
* 2 com.itcast.service..* 表示service包及其子包中所有的類
* 3 .save* 表示類中所有以save開頭的方法
* 4 (..) 表示參數是任意數量
定義通知:
事務管理
僅用四個詞解釋事務
atomic(原子性):要麼都發生,要麼都不發生。
consistent(一緻性):資料應該不被破壞。
Isolate(隔離性):使用者間操作不相混淆
Durable(持久性):永久儲存,例如儲存到資料庫中等
Spring提供了兩種事務管理方式:
程式設計式事務管理
聲明式事務管理
編寫程式式的事務管理可以清楚的定義事務的邊界,可以實作細粒度的事務控制,比如可以通過程式代碼來控制你的事務何時開始,何時結束等,與下面的聲明式事務管理相比,它可以實作細粒度的事務控制。
如果并不需要細粒度的事務控制,可以使用聲明式事務,在Spring中,隻需要在Spring配置檔案中做一些配置,即可将操作納入到事務管理中,解除了和代碼的耦合,這是對應用代碼影響最小的選擇,從這一點再次驗證了Spring關于AOP的概念。當不需要事務管理的時候,可以直接從Spring配置檔案中移除該設定.需要引入用于事務管理的命名空間(tx).
Spring并沒有直接管理事務,而是将事務的管理委托給其他的事務管理器實作.
Spring支援的事務管理器:
org.springframework.jdbc.datasource.DataSourceTransactionManager (在單一的JDBC Datasource中的管理事務)
org.springframework.orm.hibernate3.HibernateTransactionManager (當持久化機制是hibernate時,用它來管理事務)
org.springframework.jdo.JdoTransactionManager (當持久化機制是Jdo時,用它來管理事務)
org.springframework.transaction.jta.JtaTransactionManager (使用一個JTA實作來管理事務。在一個事務跨越多個資源時必須使用)
org.springframework.orm.ojb.PersistenceBrokerTransactionManager (當apache的ojb用作持久化機制時,用它來管理事務)
基于XML檔案配置事務管理器:
配置完事務管理器後,再正常的配置Bean注入對象.預設隻有運作時異常才将導緻事務復原.
基于注解配置事務管理器:
XML配置檔案中隻需要聲明事務管理器,而不需要給它"靈魂",因為"靈魂"是由注解注入,是以需要注解解析器的支援:
<tx:annotation-driven transaction-manager="txManager"/>
注冊對事務注解進行解析的處理器,将注解與事務管理器關聯起來即可.
小記:三大架構中最難的當屬三大架構的整合,本文隻是簡單的将Spring的一些常見配置記下,諸如SpringMVC也不錯,和StrutsMVC隻是封裝的不一樣.Spring強大的聲明式事務管理,常被用以業務層的封裝.