Spring初級學習小結
1.Spring是一個從實際開發中抽取出來的框架,它完成了大量開發中的通用步驟,留給開發者的僅僅是與特定應用相關的部分,從而大大地提高了企業應用的開發效率。
Spring 具有如下優點:
> 低侵入式設計, 程式碼的汙染極低。
> 獨立於各種應用伺服器, 基於Spring 框架的應用,可以真正實現Write Once 、Run Anywhere的承諾。
> Spring 的AOP 支援允許將一些通用任務如安全、事務、日誌等進行集中式處理,從而提供
了更好的複用。
> Spring 的ORM 和DAO 提供了與第三方持久層框架的良好整合, 並簡化了底層的資料庫訪間。
2. Spring框架的下載地址:---到2017.1.3最新版為4.3.5
http://repo.springsource.org/libs-release-local/org/springframework/spring/
Spring API 的線上地址:
http://docs.spring.io/spring/docs/current/javadoc-api/
Spring 涉及的相關jar包下載:
http://commons.apache.org/proper/commons-logging/download_logging.cgi
在Eclispe中安裝Spring tools 套件外掛:
Spring Tool Suite(STS) for Eclispe 3.8.3.RELEASE
安裝此外掛後可以方便的建立和修改Spring的配置檔案,並且支援提示的功能。
Properties.Editer
3.Spring專案的開發步驟:
A.建立一個動態Web專案或者Java專案;
B.匯入Spring框架的相關jar包,若是Java專案需要加入到build path中,若是Web專案需要複製到WEB-INF下的lib資料夾中。
C.建立spring配置檔案applicationContext.xml,以及其他的配置檔案,比如log4j的配置檔案。
4.當我們使用Spring 框架時, 必須使用Spring Core Container (即Spring 容器),它代表了Spring 框架的核心機制, Spring Core Container 主要由org.springframework.core 、
orgspringfamework.beans 和org.springframework.context、org.springframework.expression 四個包及其子包組成,主要提供Spring IoC 容器支援。
控制反轉(Inversion of Control, IoC):###從呼叫者角度看
使用Spring框架之後,呼叫者無需主動獲取被依賴的物件,呼叫者只要被動接受Spring容器為呼叫者的成員變數賦值即可(只要配置一個<property.../> 子元素,Spring就會執行對應的Setter方法為呼叫者的成員變數賦值)。使用Spring框架之後,呼叫者獲取被依賴物件的方式,由原來的主動獲取變成了被動接受----Rod Johnson將這種方式稱為控制反轉!
依賴注入(Denpendency Injection, DI):###從Spring容器看
Spring容器負責將被依賴物件賦值給呼叫者的成員變數----相當於為呼叫者注入它依賴的例項,Martine Fowler 稱之為依賴注入
IoC和DI,其實意義完全相同,是同一個行為的兩種表達,只是描述的角度不同而已!
5.Spring容器,建立、管理Java類,
要被管理的Bean配置有哪些配置方式?
---XML的配置檔案和註解方式;
如何初始化容器?
---使用ApplicationContext介面的兩個實現類
如何從容器中獲取Bean?
---使用ApplicationContext介面的getBean()方法。
6.將Java類放入Spring容器中有兩種方式:
A.使用XML配置檔案的方式
B.使用註解的配置方式
7.使用XML配置檔案的方式:在applicationContext.xml中
-
- 使用<bean>標籤在<beans>標籤中定義/宣告一個bean;支援的屬性:
-
- 使用classs屬性指定要例項化的物件是什麼型別,值通常為:包名.類名;
- 使用id屬性,指定物件例項化後叫什麼名字,以便後面獲取時引用;
<bean id="dao" class="dao.impl.UserDaoImpl" />
-
- 使用<property>標籤為bean物件的屬性賦值;基本型別和String型別使用value,引用型別使用ref!
<bean id="service" class="service.impl.UserServiceImpl">
<property name="dao" ref="dao"></property>
</bean>
對於內部bean的
對於list、set、陣列的<property>標籤的配置是一樣的,如:
<!-- 注入List型別 -->
<property name="list">
<list>
<!-- 定義List中的元素 -->
<value>乒乓球</value>
</list>
</property>
-
- 可以使用<constructor-arg ref="...">,在物件初始化時呼叫含有引數的建構函式,完成屬性的賦值
<bean id="boyConstructor" class="com.ddb.spring.set.BoyConstructor">
<!-- 通過構造方法注入物件 -->
<constructor-arg ref="chinaGirlFriend" />
</bean>
f.可以使用p名稱空間,來為屬性賦值:
8.使用註解的配置方式:
使用註解標註要放入Spring容器的類;使用的註解可以是:
@Component 標註一個普通的Spring Bean類
@Controller 標註一個控制器元件類
@Service 標註一個業務邏輯元件類
@Repository 標註一個DAO元件類
使用@Autowired為Java類的引用屬性自動注入值;
@Autowired
private UsaGirlFriend usaGirlFriend;
使用@Resource為方法或屬性注入需要的元件;
---此註解並不屬於Spring框架,而是屬於javax的
@Resource註解,支援name和type屬性,例如:
XML的配置檔案中配置元件自動掃描,將使用註解的Java類加入Spring容器中:
---這一步必須有!
<!-- 自動掃描包含註解的包 -->
<context:component-scan base-package="com.ddb.spring.auto" />
9.如何在Java中初始化Spring容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//以applicationContext.xml為引數初始化Spring容器上下文
說明:ApplicationContext 是Spring容器最常用的介面,有兩個實現類如下:
ClassPathXmlApplicationContext:從類載入路徑下搜尋配置檔案,並根據配置檔案來建立Spring容器; ---這種方式使用 更改普遍一些。
FileSystemXmlApplicationContext:從檔案系統的相對路徑或絕對路徑,去搜索配置檔案,並根據...
10.獲取Spring容器中的Bean:
//獲取容器中指定的id的Bean例項
UserService userService = (UserService) ctx.getBean("service");
主要有兩個方法:
Object getBean(String id) :根據容器中Bean的id來獲取指定的Bean,獲取Bean之後需要進行強制型別轉換;
T getBean(String id,Class<T> requiredType) :根據容器中Bean的id來獲取指定的Bean,但是方法帶了一個泛型引數,獲取 Bean之後不需要進行強制型別轉換;
11..AOP ( Aspect Orient Programming),也就是面向切面程式設計,在Java EE應用中,常常通過AOP 來處理一些具有橫切性質的系統級服務,如事務管理、安全檢查、快取、物件池管理等, AOP 已經成為一種非常常用的解決方案。
12.如何理解AOP:
A.在沒有AOP的時候,可能會有這樣的場景,在N多個方法中有相同功能程式碼,比如安全檢查,但是存在問題是---重複,修改困難容易出現不一致,新方法還需要這些重複的程式碼!
B.重複的問題,我可以將相同的程式碼抽取出來,統一呼叫抽取出來的方法來解決,但是存在的問題是---每個方法都顯示地知道了自己呼叫抽出來的方法,並且如果我們需要再增加日誌的操作等,就要再增加顯示呼叫日誌的函式,再增加許可權檢查,事務檢查,你會發現顯示呼叫就會越來越多。
C.AOP就可以解決上面的問題,通過切面和切入點織入需要處理的操作,而原來的業務元件卻毫無察覺。
AOP的原理和Listener有些類似,可以理解監聽的方法被呼叫,從而觸發了一些前置操作或者後置操作等!
13.AspectJ 的作用:開發者無須修改原始碼,但又可以為元件的方法新增新的功能!
14.AOP的實現分為兩類:
靜態AOP實現:編譯階段對程式進行修改,即實現對目標物件的增強,以AspectJ為代表;
動態AOP實現:在執行階段動態生成AOP代理,以實現對目標物件的增強,以SpringAOP為代表。
15.AOP 框架具有如下兩個特徵:
> 各步驟之間的良好隔離性。
> 原始碼無關性。
16.AOP程式設計,其中需要程式設計師參與的只有三個部分:
> 定義普通業務元件。
> 定義切入點, 一個切入點可能橫切多個業務元件。
> 定義增強處理,增強處理就是在AOP 框架為普通業務元件織入的處理動作。
17.Spring 有如下兩種選擇來定義切入點和增強處理。
> 基於XML 配置檔案的管理方式:使用Spring 配置檔案來定義切入點和增強處理。
> 基於註解的“零配置”方式:使用@Aspect 、@Pointcut 等註解來標註切入點和增強處理。
18.Spring AOP基於XML配置的方式:
在Spring 的配置檔案中, 所有切面、切入點和增強處理都必須定義在<aop:config>標籤元素內部。<beans ... />元素下可以包含多個<aop:config>元素, 一個<aop:config>可以包含pointcut 、advisor 和aspect 元素, 且這三個元素必須按照此順序來定義。
A .定義切面:---使用<aop:aspect>標籤
B .配置增強處理:
使用的標籤有:
<aop:before>、<aop:after>、<aop:after-returning>、
<aop:after-throwing>、<aop:around>
上面這些元素都不支援使用子元素, 但通常可指定如下屬性。
> pointcut: 指定一個切入表示式, Spring 將在匹配該表示式的連線點時織入該增強處理。
> pointcut-ref: 指定一個已經存在的切入點名稱, 通常pointcut 和pointcut-ref 兩個屬性
只需使用其中之一。
> method : 該屬性指定一個方法名, 指定切面Bean 的該方法將作為增強處理。
> throwing : 只對<aop:after-throwing>元素有效, 用於指定一個形參名,AfteThrowing 增強處理方法可通過該形參訪問目標方法所丟擲的異常。
> returning : 該屬性只對<aop:after-returning>元素有效,用於指定一個形參名, AfterReturning增強處理方法可通過該形參訪問目標方法的返回值。
C.配置切入點:---使用<aop:pointcut>標籤
標籤中可以使用的子標籤,可以通過自動提示列出來!
例如:
<bean id="dao" class="dao.impl.UserDaoImpl" />
<bean id="service" class="service.impl.UserServiceImpl">
<property name="dao" ref="dao"></property>
</bean>
<bean id="loggerBefore" class="aop.LoggerBefore" />
<bean id="loggerAfterReturning" class="aop.LoggerAfterReturning" />
<aop:config>
<aop:pointcut id="pointcut"
expression="execution(public void addNewUser(entity.User))" />
<aop:advisor pointcut-ref="pointcut" advice-ref="loggerBefore"/>
<aop:advisor pointcut-ref="pointcut" advice-ref="loggerAfterReturning"/>
</aop:config>
19.Spring AOP基於註解的配置方式:
為了啟用Spring 對註解@AspetJ 切面配置的支援
方式一:使用Spring 的XML Schema 配置方式,在Spring的applicationContext.xml檔案中的<beans>中增加:
<!-- 啟動@AspectJ 支援 -->
<aop : aspectj-autoproxy/>
方式二:使用一個Bean後處理器,在Spring 配置檔案中增加如下片段來啟用@AspecJ 支援。
<!-- 啟動@AspectJ 支援 -->
<bean class="org.springframework.aop.aspectj.annotation.
AnnotationAwareAspectJAutoProxyCreator" />
上面的配置檔案中的 AnnotationAwareAspecUAutoProxyCreator是一個Bean 後處理器,該Bean 後處理旅將會為容器中Bean 生成AOP 代理,為了在Spring 應用中啟動@AspectJ 支援,還需要在應用的類載入路徑中增加兩個AspectJ 庫:aspectjweaver.jar 和aspectjrt.jar 。
A.定義切面:使用註解:@AspectJ ,直接加到類的上一行
使用@Aspect 標註一個Java 類,該Java 類將會作為切面Bean,當我們使用@Aspect 來修飾一個Java 類之後, Spring 將不會把該Bean 當成級件Bean 處理,因此負責自動熠強的後處理Bean 將會略過該Bean,不會對該Bean 進行任何增強處理。
B.定義增強處理:註解都是加在方法之上
@Before --只能在目標方法執行之前織入增強
通常需要指定一個value 屬性值,該屬性值指定一個切入點表示式〈既可以是一個
己有的切入點, 也可以直接定義切入點表示式),用於指定該增強處理將被織入哪些切入點。
Before 處理無法阻止目標方法的執行, Before 增強處理執行時,目標方法還未獲得執行的機會,所以Before 增強處理無法訪問目標方法的返回值. 若要阻止目標方法執行,可以通過拋異常來實現。
例如:
@Before("execution(* org.crazyit.app.service.impl .*.*(..))")
@Before 註解 直接指定了切入點表示式,指定匹org.crazyit.app.service.impl 包下所有類的所有方法的執行作為切入點。
@AfterReturning 在目標方法正常完成後被織入。
例如:
@AfterReturning(returning="rvt",pointcut="execution(* org.crazyit.app.service.impl .*.*(..))") //value屬性與pointcut屬性作用一樣
public void log(Object rvt)
如果上面的log()方法中定義rvt 形參的型別是String,則該切入點只匹配lee 包下返回值型別為String 的所有方法.
可以訪問目標方法的返回值,但是不可以改變返回值!
@AfterThrowing 主要用於處理程式中未處理的異常。
@AfterThrowing( throwing="ex"
,pointcut="execution(* org.crazyit.app.service.impl .*.*(..))") //value屬性與pointcut屬性作用一樣
public void doRecoveryActions (Throwable ex)
使用throwing 屬性還有一個額外的作用:它可用於限定切入點只匹配指定型別的異
常--假如如在上面的doRecoveryActions()方法中定義了ex 形參的型別是NullPointer-
Exception ,則該切入點只匹配丟擲NullPointerException 異常的情況. 上面doRecoveryActions()方法的ex 形參型別是Throwable ,這表明該切入點可匹配丟擲任何異常的情況. AfterThrowing 處理雖然處理了該異常,但它不能完全處理異常,異常依然會傳播到上一級呼叫者
@After 不管目標方法如何結束,成功完成或者異常終止,它都會被織入;這種增強通常用於釋放資源。
@After("execution(* org.crazyit.app.service.impl .*.*(..))")
After 增強處理的作用非常類似於異常處理中finally 塊的作用一一無論如何,它總會在方法執行結束之後被織入,因此特別適用於進行資源回收。
@Around 增強的超級大Boss
@Around("execution(* org.crazyit.app.service.impl .*.*(..))")
public void save(ProceedingJoinPoint pjp)
Around 增強處理甚至可以決定目標方法在什麼時候執行,如何執行,甚至可以完全阻止目標方法的執行;可以改變執行目標方法的引數值;也可改變執行目標方法之後的返回值。
Around 增強處理的功能雖然強大,但通常需要線上程安全的環境下使用.
當定義一個Around 增強處理方法時,該方法的第一個形參必須是ProceedingJoinPoint 型別(至少包含一個形參〉, 在增強處理方法體內,呼叫ProceedingJoinPoint 的proceed()方法才會執行目標方法一一這就是Around 增強處理可以完全控制目標方法執行時機、如何執行的關鍵; 如果程式沒有呼叫ProceedingJoinPoint 的proceed()方法,則目標方法不會被執行。
呼叫ProceedingJoinPoint 的proceed()方法時,還可以傳入一個Object[]物件,該陣列中的值將被傳入目標方法作為執行方法的實參。
ProceedingJoinPoint 使用下面這些方法就可訪問到目標方法的相關資訊
> Object[] getArgs(): 返回執行目標方法時的引數。
> Signature getSignature(),返回被增強的方法的相關資訊。
> Object getTarget(): 返回被織入增強處理的目標物件。
> Object getTh is(), 返回AOP 框架為目標物件生成的代理物件。
配置applicationContext.xml,自動掃描Bean元件類與切面類:
<!-- 指定自動搜尋Bean元件,自動搜尋切面類 -->
<context:component-scan base-package="org.crazyit.app.service,org.crazyit.app.aspect">
<context:include-filter type="annotation" expression
="org.aspectj.lang.annotation.Aspect"/>
</context:component-scan>
<!-- 啟動@AspectJ 支援 -->
<aop : aspectj-autoproxy/>
C.定義切入點:
---上面的每個增強註解都含有【execution(* org.crazyit.app.service.impl .*.*(..))"】完全可以提取出來,使用切入點代替。
C1.定義切面內範圍的切入點
當myPointcut()的修飾符為private時,則為切面範圍的切入點,
引用方式:@AfterReturning(pointcut="myPointcut()”,returning="retVal")
C2.定義可以共享的切入點
當myPointcut()的修飾符為public時,則為可共享範圍的切入點,
引用方式:
附:
關於面向切面程式設計的一些術語。
> 切面(Aspect) :業務流程執行的某個特定步驟,也就是應用執行過程的關注點, 關注點可能橫切多個物件,所以常常也稱為橫切關注點。
> 連線點( Joinpoint) : 程式執行過程中明確的點,如方法的呼叫,或者異常的丟擲。Spring AOP
中,連線點總是方法的呼叫,或者說僅支援將方法呼叫作為連線點。
> 增強處理(Advice ) : AOP 框架在特定的切入點執行的增強處理。處理有"around "," before "和“ after”等型別。
> 切入點( Pointcut) :可以插入增強處理的連線點。簡而言之, 當某個連線點滿足指定要求
時,該連線點將被新增增強處理,該連線點也就變成了切入點。
> 引入:將方法或欄位新增到被處理的類中。Spring 允許引入新的介面到任何被處理的物件。
例如,你可以使用一個引入,使任何物件實現lsModified 介面,以此來簡化快取。
> 目標物件:被AOP 框架進行增強處理的物件,也被稱為被增強的物件。如果AOP 框架是通
過執行時代理來實現的,那麼這個物件將是一個被代理的物件。
> AOP 代理: AOP 框架建立的物件,簡單地說,代理就是對目標物件的加強。Spring 中的AOP
代理可以是JDK 動態代理,也可以是CGL舊代理。前者為實現介面的目標物件的代理,後者為不實現介面的目標物件的代理。
> 織入( Weaving ) : 將增強處理新增到目標物件中,並建立一個被增強的物件( AOP 代理)
的過程就是織入。織入有兩種實現方式:編譯時增強(例如AspectJ )和執行時增強(例如
CGLIB ) 。Spring 和其他純JavaAOP 框架一樣,在執行時完成織入.