初始Spring 文件 完整版
初始Spring
1.Spring官網
spring.io
01.
IOC(Inverse of Control)控制反轉
02.
AOP(Aspect Oritend Programming)面向切面程式設計
03.
OOP(Object Oritend Programming)面向物件程式設計
四大核心
抽象 封裝 繼承 多型
04.
OOD(Object Oritend Programming)面向物件設計
工程師 架構師
05.
OOA(Object Oritend Analesis) 面向物件分析
2.物件之間的關係(面向物件分析OOA、面向物件設計OOD、面向物件程式設計OOP)
分析 ----------- 設計 ----------- 程式設計
是 泛化 繼承 extends
能 實現 介面 implements
有 關係 成員變數
用 依賴 方法中區域性變數
3.框架和工具類的區別
工具類
對程式碼的一個簡單封裝
框架
站在整個軟體系統,所有可能設計到的事物、安全、頁面、請求排程、底層ORM、日誌。等等東西整合的一種手段
*不用瞭解架構,但可以做出具體實現
4.spring組成模組(從下到上)
01.Test
測試部分
02.Core Container
核心部分
03.AOP/Instrumentatio
AOP
面向切面程式設計
Instrumentation
獲取計算機軟體或者硬碟狀態資料的技術。類似如探針
4.Data Access/Web
Data Access
資料訪問部分
Web
網際網路部分
5.Core Container
01.Beans
02.Core
03.Context
04.SpEL
6. IOC和DI區別
IOC
控制反轉(Inversion of Control)
理解一
元件物件的控制權從程式碼本身轉義到外部容器(spring容器)
理解二
在xml中控制,側重於原理(就是xml中配置bean節點)
DI
Dependency Injection(依賴注入)給物件注入屬性值
關係
它們是spring核心思想的不同方面的描述。站在不同維度對同一個概念或者事物的解釋
理解一
建立物件例項時,為這個物件注入屬性值或其他物件例項(域屬性),側重於實現
01.區別
IOC
側重於原理
xml配置物件,主要控制反轉
DI
側重於實現
物件初始化過程注入屬性值
小結
IOC和DI是站在不同維度對同一個事物進行描述
7.域屬性
自定義物件型別,作為另外一個物件的屬性
8.第一案例
01.引入jar包
context、beans、core、spEl
*引入spring的核心jar包
02.建立實體類
03.建立applicationContext.xml
<bean id="物件引用名稱" class="引用類的全類名">
<property name="屬性名" value="屬性值">
</bean>
*bean中只能配置實現類,不能配置介面
04.測試類
//使用Application物件指向的是上下文(Spring容器)
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//獲取為Object型別,必須要強制型別轉換為引用型別
context.getBean("bean節點id屬性");
9.AOP(面向切面程式設計)
01.AOP的目標
讓我們可以“專心做事”
02.AOP原理
02.1
將複雜的需求分解出不同方面,將散佈在系統中的公共功能集中解決
02.2
採用代理機制組裝起來執行,在不改變原程式的基礎上對程式碼段進行增強處理,增加新的功能
03.AOP圖解
黃色(Logging):日誌
紅色(security):事務
綠色(Persistence):許可權
10.配置AOP,增強業務
01.建立一個aop包
02.建立一個增強類實現介面中的方法
02.1介面
MethodBeforeAdvice
實現前置增強
AfterReturningAdvice
實現後置增強
02.2在applicationContext中引用強制型別類
<bean id="標識" class="全類名"></bean>
03.在ApplicationContext.xml中配置aop:config節點
11.定義切入點
01.簡單說就是連線點的檢查條件
<aop:config>
<!--切點-->
<aop:pointcut id="mypoint" expression="execution(* *..service.*.*(..))"></aop:pointcut>
<!--顧問-->
<aop:advisor advice-ref="AdviceBefore" pointcut-ref="mypoint"></aop:advisor>
</aop:config>
*屬性
advice-ref
強制型別:前置還是後置
pointcut-ref
鎖定規則:什麼樣的方法被鎖定
02.表示式的切入規則舉例(expression)
02.1
public * addNewUser(entity.User)
“*”表示匹配所有型別的返回值
02.2
public void *(entity.User)
“*”表示匹配所有方法名
02.3
public void addNewUser(..)
“..”表示匹配所有引數個數的型別
02.4
* com.service.*.*(..)
匹配com.service包下所有類的所有方法
02.5
* com.service..*.*(..)
匹配com.service包及其子包下所有類的所有方法
03.切點表示式
03.1顧問包裝通知
execution([modifiers-pattern?]訪問修飾符
ref-type-pattern 返回值型別
[declaring-type-pattern?] 全限定性類名
name-pattern(param-pattern) 方法名(引數名) 包名.型別名.方法名
[throws-pattern?] 丟擲異常型別)
03.2方法簽名(切面表示式)
切入點表示式要匹配的物件就是目標物件的方法名。所以,execution表示式中明顯就是方法的簽名。
注意:表示式中加[]的部分表示可省略部分
符號 意義
* 0至多個任意字元
.. 用在方法引數中,表示任意多個引數
或用在報名後,表示當前包及其子包路徑
+ 用在類名後,表示當前類及其子類
或用在介面後,表示當前介面及其實現類
案例
execution(public * *(..)) 任意公共方法
execution(* set*(..)) 任何一個以“set”開頭的方法
12.構造注入
01.實體類中建立構造方法
02.在ApplicationContext.xml中bean節點中使用constructor-arg節點注入
如:
<bean id="Student" class="cn.zw.entity.Student">
<constructor-arg index="0" value="小黑"></constructor-arg>
<constructor-arg index="1" ref="index01"></constructor-arg>
</bean>
*
index
代表的是構造方法的引數下標,從0開始
value
代表的是對應構造引數注入的值
ref
給域屬性賦值時使用
13.P名稱空間注入
01.使用屬性而不是子元素的形式配置bean的屬性,從而簡化了配置程式碼
02.步驟
02.1
使用前要現在Spring配置檔案中引入p名稱空間
xmlns:p="http://www.springframework.org/schema/p"
*也可以使用快捷方式進行匯入Alt+Enter
02.2
使用p名稱空間注入屬性值
<bean id="Student" class="cn.zw.entity.Student" p:name="小黑" ></bean>
*通過bean節點中的屬性p:應用類中的屬性名賦值,如果是域屬性跟上面的方法類似,p:stu-ref=""引用賦值
14.集合屬性注入
<bean id="標識" class="引用類的型別全名稱">
<!--給陣列中注入-->
<property name="集合屬性名">
<array>
<value>小黑</value>
<value>小紅</value>
<value>小白</value>
</array>
</property>
<!--給List集合中注入-->
<property name="集合屬性名">
<list>
<value>小號</value>
<value>中號</value>
<value>大號</value>
</list>
</property>
<!--給Set集合中注入-->
<property name="集合屬性名">
<set>
<value>屬性值。。</value>
<value>小安</value>
<value>等等</value>
</set>
</property>
<!--給Map集合中注入-->
<property name="集合屬性名">
<map>
<entry key="key屬性值">
<value>value屬性值</value>
</entry>
</map>
</property>
<!--給Properties型別集合中注入-->
<property name="集合屬性名">
<props>
<prop key="key屬性值">value屬性值</prop>
</props>
</property>
</bean>
15.SpringBean單列和多列設定
01.建立單例類
01.1使用IDEA自動建立
建立Java Class時把Kind選擇為Singleton就可以了
02.預設Spring中的bean都是單例的。可以通過設定bean中的屬性scope值改變
單例:singleton
多例:prototype
16.自動裝配
01.通過設定bean節點中的autowire屬性
01.1
通過屬性型別自動裝配
autowire屬性設定為byType
實現思路
通過物件中的屬性型別與Mapper檔案中的bean節點的型別進行匹配
缺點
如果Mapper檔案中有多個相同的bean節點型別時會出現編譯異常
01.2
通過屬性名稱自動裝配
autowire屬性值設定為byName
實現思路
通過物件中的屬性名稱與Mapper檔案中bean節id名稱進行匹配
17.註解
01.概念
Annotation,也叫元資料(MetaData)。一種程式碼級別的說明。它是JDK1.5及以後版本引入的一個特性,與類、介面、列舉是在同一個層次。它可以宣告在包、類、欄位、方法、區域性變數、方法引數等的前面,用來對這些元素進行說明
02.註解的本質
就是有一個@的介面
原型
//元元素,表示註釋型別的程式元素的種類
@Target{TYPE,FIELD,HETHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE}
//保留,通知編譯器如何處理
@Retention(RetentionPolicy.SOURCE)
public @interface 註解名稱{}
03.使用步驟(基於註解的依賴注入)
01.在ApplicationContext檔案中匯入名稱空間
01.1
xmlns:context="http://www.springframework.org/schema/context"
01.2在xsi:schemaLocation下新增
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
01.3 注意
也可以使用快捷方式進行匯入Alt+Enter
01.4 在beans節點中新增(新增掃描器)
<context:component-scan base-package="cn.zw.entity"></context:component-scan>
*base-package指定的是使用註解的類包名
02.在實體類中
02.1
類上方
@Component 不按照上面三個註解分類,就用此註解
@Repository 持久層
@Service 業務邏輯層
@Controller 控制器
如:@Component("use")
use表示bean節點的id
*如註解中沒有定義值,預設是類的小寫
屬性注入值
@Value("")
04.域屬性注入值
04.1
使用jdk提供的註解
@Resource(name = "")
name指定的是bean節點的id
04.2
使用spring提供的註解
@Autowired //表示自動連線
@Qualifier(value = "")
value指定的是bean節點的id
04.3小結
01.
@Resource預設安裝byName的方式進行裝配。byName的含義:擁有該屬性欄位名稱必須和Spring容器中現有bean的id相同。@Resource比較只能,當根據byName方法裝配失敗後,它會繼續嘗試使用byType的方式進行裝配,即使型別相同也可以完成裝配。
02.
@Autowired預設安裝byType的方式進行裝配,擁有該註解的欄位型別必須和Spring容器中現有型別相同。如果發現與欄位想用的bean會導致異常。
03.
@Qualifier將此註解跟@Autowired混合使用時,含義是強制使用byName的方式進行裝配,不匹配直接導致異常
06.javax包屬於jdk
18.靜態代理
在原有的方法上進行方法增強
01.1
缺點:硬碟中會建立真正的物理類
01.2
主題
抽象主題(介面) 真實主題(類) 代理主題(類)
關係
抽象主題中定義方法,真實主題和代理主題都實現抽象主題並實現當中的方法。真實主題負責具體實現,代理主題物件引用真實主題物件的例項後封裝並對真實進行增強。
測試類中抽象主題物件例項化真實主題物件,並放入代理主題物件的封裝中。後呼叫代理物件的方法,進行方法增強
簡化‘’
抽象主題
賦值定義方法
真實主題
實現抽象主題中方法
代理主題
用於增強真實主題中的方法
19.動態代理
19.1
JDK動態代理
要被代理的物件必須有介面
01.使用步驟(示例)
final IStudent iStudentimpl = new IStudentimpl();
IStudent iStudent = (IStudent) Proxy.newProxyInstance(iStudentimpl.getClass().getClassLoader(), iStudentimpl.getClass().getInterfaces(), new InvocationHandler() {
/*
* proxy:代理物件
* method:目標型別的方法(方法的型別)
* args:方法引數(目標方法的引數)
* */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("增強中。。。。。。。");// 寫增強的方法
Object invoke = method.invoke(iStudentimpl,args);//相當於執行目標型別的方法
return invoke;
}
});
iStudent.doShow();
02.注意
Proxy類和InvocationHandler介面進行導包是要使用java.lang下的包
19.2
CGLIB動態代理(回撥型別)
01.
Cglib 底層,注入,編譯器已經注入了
本質
在記憶體中生成被代理類(目標類)的子類
特點
可以在沒有介面的情況下代理
對於不使用介面的業務類,無法使用JDK動態代理,cglib採用非常底層的位元組碼技術,可以為一個類建立子類。
02.示例
final cglibDay cglib = new cglibDay();
//CGLIB動態代理
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(cglib.getClass());
//排程回撥函式
enhancer.setCallback(new MethodInterceptor() {
/*
* o:代理物件
* method:目標型別的方法
* objects:目標方法引數
* methodProxy:代理類的方法
* */
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("回撥成功");
Object invoke = methodProxy.invoke(cglib, objects);
return invoke;
}
});
cglibDay cglibDay = (cglibDay) enhancer.create();
cglibDay.Show();
20.回撥函式
一個方法執行完成後再執行某一段程式碼的方法
21.經典AOP
01.代理工廠Bean
前置增強 MethodBeforeAdvice 方法執行之前執行
後置增強 AfterReturningAdvice 方法執行之後執行
環繞增強 MethodInterceptor 方法執行前後都有執行
異常增強 ThrowsAdvice 方法執行中出現異常就捕捉
02.使用bean代理工廠實現前置增強
<!--目標型別-->
<bean id="id1" class="cn.Enhance.zw.IStudentImpl"></bean>
<!--增強 通知-->
<bean id="id2" class="cn.Enhance.zw.people"></bean>
<!--代理工廠bean-->
<bean id="zq" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--目標型別-->
<property name="target" ref="id1"></property>
<!--增強-->
<property name="interceptorNames" value="id2"></property>
</bean>
03.使用bean代理工廠實現後置增強
Mapper檔案的配置跟上面一樣,在增強類中需要實現相應的介面
04.使用bean代理工廠實現環繞增強
Mapper檔案的配置跟上面一樣,在增強類中的方法實現
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("前置增強中。。。");
methodInvocation.proceed();
System.out.println("後置增強中。。。。");
return null;
}
*需要在前後增強之間排程MethodInvocation物件的proceed方法,用於排程目標物件中的方法
05.使用bean代理工廠實現異常增強
Mapper檔案的配置跟上面一樣,在增強類中的方法實現
public void afterThrowing(Exception ex){
System.out.println("空指標異常!!!");
}
*需要寫介面中註釋裡的方法,方法名需要和註釋中定義的一致
22.顧問(Advisor)
01.
通知Advice是Spring提供的一種切面(Aspect)。但其功能過於簡單,只能將切面織入到目標類的所有目標方法中,無法完成將切面織入到指定目標方法中。
顧問Advisor是Spring提供的另一種切面。其可以完成更為複雜的切面織入功能,能選擇性的增強切面中的部分方法。
PointcutAdvisor是顧問的一種,可以指定具體的切點。顧問將通知進行包裝,會根據不同的通知型別,在不同的時間點,將切面織入到不同的切入點
02.PointcutAdvisor介面中常用實現類
02.1
NameMatchMethodPointcutAdvisor
名稱匹配方法切入點顧問
02.2
RegexpMethodPointcutAdvisor
正則表示式方法切入點顧問
03.例項(名稱匹配切入點顧問)
在ApplicationContext檔案中定義顧問包裝通知
01.示例
<!--顧問-->
<bean id="Iadviser" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<!--增強-->
<property name="advice" ref="Enhance"></property>
<!--顧問-->
<property name="mappedNames" value="Show1,Show2"></property>
</bean>
*顧問中的value可以是N個方法名,也可以使用萬用字元
*id賦值給代理工廠中的interceptorNames屬性值中
04.例項(正則表示式方法切入點顧問)
在在ApplicationContext檔案中定義顧問包裝通知
<!--顧問-->
<bean id="Iadviser" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!--增強-->
<property name="advice" ref="Enhance"></property>
<!--顧問-->
<property name="pattern" value=".*Show.*"></property>
</bean>
*顧問中的value填寫正則表示式,鎖定的方法為方法的全路徑
*id賦值給代理工廠中的interceptorNames屬性值中
23.顧問和通知的區別
顧問可以選擇性的增強,而通知是直接把所有方法都增強
24.正則表示式
用於匹配
運算子 名稱 意義
. 點號 表示任意單個字元
+ 加號 表示前一個字元出現一次或者多次
* 型號 表示前一個字元出現0次或者多次
25.自動代理實現
01.Advisor
01.1正則自動代理生成器
DefaultAdvisorAutoProxyCreator
注意:切面只是顧問,對所有的物件都增強
01.2語法
<!--目標物件-->
<bean id="id1" class="cn.AutomaticAgent.IStudentImpl"></bean>
<!--增強-->
<bean id="enhance" class="cn.AutomaticAgent.Preposition"></bean>
<!--顧問-->
<bean id="adviser" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!--增強-->
<property name="advice" ref="enhance"></property>
<!--顧問-->
<property name="patterns" value=".*se.*"></property>
</bean>
<!--自動代理-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
*在測試類中使用getBean時使用目標物件的id進行入參
02.1名稱自動代理生成器
BeanNameAutoProxyCreator
*切面只是顧問,對所有物件都增強
02.2語法
<!--目標物件-->
<bean id="id1" class="cn.AutomaticAgent.IStudentImpl"></bean>
<bean id="id2" class="cn.AutomaticAgent.IBookImpl"></bean>
<!--增強-->
<bean id="enhance" class="cn.AutomaticAgent.Preposition"></bean>
<!--顧問-->
<bean id="adviser" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!--增強-->
<property name="advice" ref="enhance"></property>
<!--顧問-->
<property name="patterns" value=".*se.*"></property>
</bean>
<!--自動代理-->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<!--目標型別-->
<property name="beanNames" value="id1,id2"></property>
<!--切點-->
<property name="interceptorNames" value="adviser"></property>
</bean>
*自動代理中beanNames是String型別陣列,所以可以對多個目標型別
*可以寫入顧問和通知
26.AspectJ
01.概念
01.1
一個面向切面的框架,它擴充套件了Java語言,定義AOP語法,能夠在編譯器提供程式碼的織入
01.2
@AspectJ是AspectJ5新增的功能,使用JDK5.0註解技術和正規的AspectJ切點表示式語言描述語言
01.3
Spring通過整合AspectJ實現了以註解的方式定義增強類,大大減少了配置檔案中的工作量
02.注意
使用@AspectJ,首先要保證所用的JDK是5.0及以上的版本。將Spring的asm模組新增到類路徑中,以處理@AspectJ中所描述的方法引數名
27.AOP的常見術語
01.
JoinPoint(連線點):所謂連線點是指那些被攔截到的點。在spring中,這些點指的是方法,因為spring只支援方法型別的連線點。
02.
Pointcut(切入點):所謂切入點是指我們要對哪些JoinPoint進行攔截的定義。
03.
Advice(通知/增強):所謂通知是指攔截到JoinPoint之後所要做的事情就是通知。通知分為前置通知,後置通知,異常通知,最終通知,環繞通知 ,Advice是面向方法的
04.
Introduction(引介/引入):Introduction是一種特殊的Advice,是面向類的,可以在執行期間為類動態地新增一些方法或欄位。
05.
Target(目標物件):代理的目標物件
06.
Weaving(織入):將Advice(增強)應用給Target(目標物件),建立Proxy的過程
07.
Proxy(代理物件):將advice織入target,生成代理物件
08.
Aspect(切面):是切入點和通知(增強)的總和
--------------------小結--------------------------
切點
匹配到切點表示式的一批方法
連線點
目標型別中所有方法都是連線點
切面
增強類(切點+增強)
織入
將增強和目標物件進行繫結的過程
代理物件
將增強和目標物件進行繫結後的結果
目標物件
代理的目標物件
增強
攔截到 連線點後(切點)要做的事情就是增強
引介
一種特殊的Advice
*切面和代理物件的區別
程式碼層面:切面就是代理物件
概念層面:代理物件就是切面
28.切面(Aspect)
增強類(切點+增強)
01.概念
無縫面向切面擴充套件的框架,橫切關注點AspectJ(也就是AOP)的動機是發現那些使用傳統的程式設計方法無法很好處理的問題。考慮一個要在某些應用中實施安全策略的問題。安全性是貫穿於系統所有模組間的問題,每個模組都需要應用安全機制才能保證整個系統的安全性,很明顯這裡的安全策略的實施問題就是一個橫切關注點,使用傳統的程式設計解決此問題非常的困難而且容易產生差錯,這就正是AOP發揮作用的時候了。@AspectJ 使用了Java5 的註解, 可以將切面宣告為普通的Java類(POJO)。
02.增強類中使用註解
02.1增強類
@Aspect
02.2前置增強
@Before
相當於BeforeAdvice
* 就在方法之前執行.沒有辦法阻止目標方法執行的.
02.3後置增強
@AfterReturning
相當於AfterReturningAdvice、
* 後置通知,獲得方法返回值.
03.4環繞增強
@Around
相當於MethodInterceptor
* 在可以方法之前和之後來執行的,而且可以阻止目標方法的執行
03.5異常增強
@AfterThrowing
相當於ThrowAdvice
@After 最終final通知,不管是否異常,該通知都會執行
03.ApplicationContext檔案中配置(案例)
<!--目標型別-->
<bean id="service" class="cn.AnnotationAutomaticAgent.IStudentImpl"></bean>
<!--增強-->
<bean id="enhance" class="cn.AnnotationAutomaticAgent.Preposition"></bean>
<!--自動代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
*在測試類中使用getBean時使用目標物件的id進行入參
04.環繞增強
public void CShow(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("環繞,前置增強中。。。。");
pjp.proceed();
System.out.println("環繞,後置增強中。。。。");
}
*ProceedingJoinPoint代表目標型別物件
05.異常增強
@AfterThrowing(value = "execution(* *..AnnotationAutomaticAgent.*.insert(..))",throwing = "ex")
*throwing:代表捕獲到的異常物件,方法中入參是註解定義的值要和方法入參名稱一致
29.PointCut註解
[email protected]
簡單說就是在增強類中把註解當中的切點表示式提取出來,方便排程
02.案例
@Pointcut("execution(* *..AnnotationAutomaticAgent.*.select(..))")
public void select(){}
@Pointcut("execution(* *..AnnotationAutomaticAgent.*.delete(..))")
public void delete(){}
@Before("select()||delete()")
public void AShow(){
System.out.println("前置增強成功!!!");
}
*在增強的註解中直接排程方法即可,效果一致
“||”是或者,實現多個方法的增強
30.AspectJ基於XML的AOP實現 (開發常用)
01.AOP配置
<aop:config>
<!--切點-->
<aop:pointcut expression="execution(* *..ISomeService.doFirst(..))" id="doFirstPointcut"/>
<aop:pointcut expression="execution(* *..ISomeService.doSecond(..))" id="doSecondPointcut"/>
<aop:pointcut expression="execution(* *..ISomeService.doThird(..))" id="doThirdPointcut"/>
<aop:aspect ref="myAspect">
<!--增強 通知-->
<aop:before method="before" pointcut-ref="doFirstPointcut"/>
<aop:before method="before(org.aspectj.lang.JoinPoint)" pointcut-ref="doFirstPointcut"/>
<aop:after-returning method="afterReturing" pointcut-ref="doSecondPointcut"/>
<aop:after-returning method="afterReturing(java.lang.String)" pointcut-ref="doSecondPointcut" returning="result"/>
<aop:around method="around" pointcut-ref="doSecondPointcut"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="doThirdPointcut"/>
<aop:after-throwing method="afterThrowing(java.lang.Exception)" pointcut-ref="doThirdPointcut" throwing="ex"/>
<aop:after method="after" pointcut-ref="doThirdPointcut"/>
</aop:aspect>
</aop:config>
02.增強類
public class MyAspect {
// 前置通知
public void before(){
System.out.println("前置通知方法before()");
}
public void before(JoinPoint jp){
System.out.println("前置通知方法before() jp = " + jp);
}
// 後置通知
public void afterReturing(){
System.out.println("後置通知方法");
}
public void afterReturing(String result){
System.out.println("後置通知方法 result = " + result);
}
// 環繞通知
public Object around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("環繞通知方法,目標方法執行之前");
// 執行目標方法
Object result = pjp.proceed();
System.out.println("環繞通知方法,目標方法執行之後");
return ((String)result).toUpperCase();
}
// 異常通知
public void afterThrowing(){
System.out.println("異常通知方法");
}
public void afterThrowing(Exception ex){
System.out.println("異常通知方法 ex = " + ex.getMessage());
}
// 最終通知
public void after(){
System.out.println("最終通知方法");
}
}
31.jdbcTemplate
持久層框架
Date----》DB
01.jdbc
效能高,但是最low,程式碼最多,控制的力度最細
02.jdbctils
給一個sql,返回一個結果
03.研發jdbcTemplate
03.1需要的jar包
<!--spring JDBC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<!--mysqlDriver-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
03.2開發分層
dao、entity、service
*dao層實現類需要繼承JdbcDaoSupport類,實現this.getJdbcTemplate().query()/update()方法
03.3編寫配置檔案
資料來源、jdbcTemplate繫結資料來源、dao、service
*測試類直接排程bean(service)節點中的id
04.案例
04.1dao層方法實現類
@Override
public List<classes> Show() {
String sql = "select * from classes";
List<classes> query = this.getJdbcTemplate().query(sql, new RowMapper<classes>() {
/*
* ResultSet 讀取器
* i 讀取器讀取的第幾條記錄
* */
@Override
public classes mapRow(ResultSet resultSet, int i) throws SQLException {
classes ce = new classes();
ce.setId(resultSet.getInt("id"));
ce.setCname(resultSet.getString("cname"));
return ce;
}
});
return query;
}
04.2配置檔案(Spring內建資料來源)
<!--資料來源-->
<bean id="Driver" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///managementlanguage"></property>
<property name="username" value="root"></property>
<property name="password" value=""></property>
</bean>
<!--jdbcTimplate 繫結 資料來源-->
<bean id="jdbcTimplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="Driver"></property>
</bean>
<!--dao-->
<bean id="Dao" class="cn.Spring_jdbcTimplate.dao.IClassesImpl">
<property name="jdbcTemplate" ref="jdbcTimplate"></property>
</bean>
<!--service-->
<bean id="service" class="cn.Spring_jdbcTimplate.service.IClassServiceImpl">
<property name="iClasses" ref="Dao"></property>
</bean>
*測試類getBean指定的是service節點id
04.3
配置檔案關聯properties檔案
<context:property-placeholder location="classpath: properties檔案"></context:property-placeholder>
*classpath屬性指定的就是properties檔案
05.四種配置資料來源的方式
05.1
Spring內建的資料來源
名稱空間
DriverManagerDataSource
依賴
<!--spring JDBC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
05.2
dbcp(apache)
名稱空間
BasicDataSource
依賴
<!--dbcp-->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
05.3
C3P0
名稱空間
ComboPooledDataSource
依賴
<!--c3p0-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
05.4
druid(alibaba)
名稱空間
DruidDataSource
依賴
<!--druid-->
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.29</version>
</dependency>
05.5 小結
Spring內建資料來源、dbcp、druid中子節點屬性名稱一致。
C3P0:
driverClass、jdbcUrl、user、password
32.事務
01.概念
能保證N個執行過程可以全部執行成功或者全部回滾到初始狀態的機制就是事務
02.四大特性
02.1
原子性
事務中多個操作不可分割的
02.2
一致性
事務操作完成後的結果,資料一定要處於一致性的狀態
02.3.
隔離性
兩個事務之間執行結果或者執行過程互補干擾
02.4
永續性
事務操作的結果。永久的持久化到硬碟上
03.事務回滾規則
03.1檢查異常
提交
03.2執行時異常
回滾
33.Spring事務管理
01.Spring在企業開發中,能靈活的和其他框架進行整合,Spring職責:進行bean管理、事務控制
01.1
核心介面
PlatformTransactionManager
平臺事務管理器,提供各個框架進行事務管理
Commit 進行事務提交
Rollback 進行事務回滾
TransactionStatus 返回值是事務的狀態
TransactionDefinition
事務定義(配置)資訊(隔離、傳播、超時、只讀),相當於靜態屬性
02.非ORM事務管理機制(事務管理器)
DataSourceTransaction,用於JDBC、JDBCTemplate、MyBatis、DataSourceTransactionManager。Hibernate無法使用,因為它有單獨的事務管理器HibernateTransactionManager,需要提前引入依賴
02.1語法
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--繫結資料來源-->
<property name="dataSource" ref="資料來源id"></property>
</bean>
*用處:資料來源被事務管理,引用事務的管理器
34.事務控制
01事務代理工廠bean
<!--事務管理代理工廠bean-->
<bean class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" id="stockServiceProxy">
<!--繫結事務管理器-->
<property name="transactionManager" ref="事務管理器"/>
<!--目標物件-->
<property name="target" ref="service節點"/>
<!--事務的屬性-->
<property name="transactionAttributes">
<props>
<prop key="執行方法名稱">事務隔離級別,事務的傳播行為,[事務回滾型別]</prop>
<!--
<prop key="方法名">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
事務隔離級別
讀已經提交、讀取未提交、可重複讀、序列化
-->
</props>
</property>
</bean>
*測試階段調取事務代理工廠的id
35.註解事務
01.配置檔案中新增
<tx:annotation-driven transaction-manager="事務管理器id"></tx:annotation-driven>
02.service分層實現類的方法上添註解
@Transactional()
//rollbackFor=事務回滾型別.class
03.使用原始service物件id進行排程
36.AspectJ配置事務
01.語法
<!--增強-->
<tx:advice id="idAdvice" transaction-manager="事務管理器id">
<tx:attributes>
<!--隔離級別--> <!--傳播行為-->
<tx:method name="方法名" isolation="DEFAULT" propagation="REQUIRED" rollback-for="事務回滾型別"/>
</tx:attributes>
</tx:advice>
<!--AOP節點-->
<aop:config>
<!--切點-->
<aop:pointcut id="mypointcut" expression="execution(* *..integrationSSM.service.*.*(..))"></aop:pointcut>
[<!--切面-->]
<!--顧問-->
<aop:advisor advice-ref="idAdvice" pointcut-ref="mypointcut" ></aop:advisor>
</aop:config>
37.事務的隔離級別、傳播行為
01.隔離級別
原子性 (atomicity):強調事務的不可分割.
一致性 (consistency):事務的執行的前後資料的完整性保持一致.
隔離性 (isolation):一個事務執行的過程中,不應該受到其他事務的干擾
永續性(durability) :事務一旦結束,資料就持久到資料庫
02.傳播行為
01.1.PROPAGATION_REQUIRED
支援當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。
01.2.PROPAGATION_SUPPORTS
支援當前事務,如果當前沒有事務,就以非事務方式執行。
01.3.PROPAGATION_MANDATORY
支援當前事務,如果當前沒有事務,就丟擲異常。
01.4.PROPAGATION_REQUIRES_NEW
新建事務,如果當前存在事務,把當前事務掛起。
01.5.PROPAGATION_NOT_SUPPORTED
以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
01.6.PROPAGATION_NEVER
以非事務方式執行,如果當前存在事務,則丟擲異常。
01.7.PROPAGATION_NESTED
如果當前存在事務,則在巢狀事務內執行。如果當前沒有事務,則進行與PROPAGATION_REQUIRED類似的操作。
SSM整合
1.整合
整合不是簡單的兩個框架jar包的堆砌。而是將其中一個框架的一部分工作交給另外一個框架進行維護。
2.框架之間的職責
01.Spring
各種bean的管理和事務控制
02.Spring MVC
負責請求的派發和排程
03.MyBatis
持久層(DB進行互動)用高階介面封裝低階操作
3.框架的依賴
01.Spring
spring-core、spring-beans、spring-spel、spring-context、spring-jdbc、spring-tx
02.MyBatis
mybatis-core
4.DAO實現類的命名規則
01.如果介面命名規範是IXXXDAO,記憶體中構造的介面實現類的名稱就是它本身
02.如果介面命名規範是XXXDAO,那麼記憶體中架構的介面實現類的名稱為xXXDAO
5.Application和ServletContext
01.application是九大內建物件當中,生命週期最長的一個物件,因為它從程式啟動,一直到程式消亡。都可以被訪問到。那麼application只是Web容器(eg.Tomcat)中的一個例項
02.ServletContext正是application這個物件的型別。雖然ServletContext裡面的內容在任何地方都可以訪問。我們為什麼不將初始化Spring容器這件事也放到ServletContext中。Spring容器是什麼?就是一個物件Application
6.思路
我只要能在tomcat啟動的某個時機,去註冊一個監聽器,監聽器中可以將Spring初始化,並且放入ServletContext中。以後在任何一個Servlet中。我們都可以共享一個Spring容器。問題就轉化成了如何通過程式碼獲取到該Spring容器,我們可以使用一個工具類
WebApplicationContext wac =WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
7.Spring整合JavaWeb(Servlet)
藉助Tomcat來執行web應用
ServletContext到底是什麼?
解析:在jsp中,他就是內建物件application的型別,在servlet中就是Servlet上下文
01.對於Web應用來說,ServletContext物件是唯一的,一個Web應用,只有一個ServletContext物件。該物件是在Web應用裝載時初始化的,即在Web應用裝載時自動執行介面ServletContext的初始化方法。
02.該初始化方法在整個應用中只會執行一次。若將Spring容器的建立語句放到ServletContext的初始化方法中執行,並將建立好的Spring容器作為ServletContext的屬性放入其中。以後再需要Spring容器,直接讀取該屬性值即可。
03.ServletContext物件生命週期與Web應用的相同。即放在其中的屬性為全域性屬性。所以,放入ServletContext中的Spring容器,在整個應用的生命週期中均可被訪問。這樣就可以保證Spring容器在Web應用中的唯一性了。
04.上述的這些工作,已經被封裝在Spring的jar包相關的API中spring-web-4.2.0.RELEASE.jar
8.語法
<!--資料來源-->
<bean id="DataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--繫結properties檔案-->
<context:property-placeholder location="classpath:jdbc2.properties"></context:property-placeholder>
<!--SqlSessionFactory-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="資料來源"></property>
<property name="configLocation" value="classpath:MyBatis大配置檔案"></property>
</bean> <!--MyBatis大配置檔案中只有別名配置-->
<!--Dao-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="dao層路徑"></property>
</bean>
<!--Service層注入dao實現-->
<bean id="bookservice" class="cn.BooksSSMIntegration.service.IBookDAOServiceImpl">
<property name="iBookDAO" ref="實現類"></property>
</bean>
<!--*新增Dao層實現類時報紅,不用管。跟介面名一致即可-->
<!--事務管理器-->
<bean id="TransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="資料來源"></property>
</bean>
<!--註解事務-->
<tx:annotation-driven transaction-manager="TransactionManager"></tx:annotation-driven>
9.包裝整個應用中Spring容器的唯一(語法)
01.web.xml檔案中
<!--context-param-->
<context-param>
<!--上下文監聽器型別的父類屬性,Spring配置檔案的路徑-->
<param-name>contextConfigLocation</param-name>
<!--spring配置檔案-->
<param-value>classpath:BooksSSMIntegration.xml</param-value>
</context-param>
*應用程式的整個Servlet物件
<!--監聽器-->
<listener>
<!--引用:上下文初始化監聽器類-->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
02.測試類
ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext());
*直接獲取Spring容器例項