java-spring-2

一 學習大綱

? ? ? ?1.? 動態代理設計模式(JDK和cglib)

? ? ? ?2.? AOP詳解

? ? ? ?3.? AOP中幾種通知類型

? ? ? ?4.兩種實現方式(Schema-base和Aspectj)

二 知識點詳解

? ? ? ?1. AOP:中文名稱 面向切面編程

? ? ? ?2 英文全稱:Aspect Object Programming

? ? ? ?3 正常程序執行流程都行縱向執行流程,spring Aop 又叫面向切面編程,在原有的縱向執行流程中添加橫切面

? ? ? ?3.1 不需要修改原有程序代碼,優點:1.高擴展性,2. 原有功能相當于釋放部分邏輯,讓職務更加明確。


4.面向切面編程是什么?

? ? ? 4.1在程序原有的縱向流程執行中,針對某一個或者某一些方法添加通知,形成橫切面向過程就叫做面向切面編程。

5.常用概念

? ? ? 5.1 原有功能:切點,pointcut

? ? ? 5.2 前置通知:在切點之前執行的功能.before advice

? ? ? 5.3 后置通知:在切點之后執行的功能,after advice

? ? ? 5.4 在切點執行過程中出現的異常,會觸發異常通知 throws advice

? ? ? 5.5 所有功能總稱叫做切面

? ? ? 5.6 織入:把切面嵌入到原有功能的過程叫做織入

6 spring提供了2種Aop實現方式

? ? ?6.1 Schema-based

? ? ? ? ? ?6.1.1 每個通知都需要實現接口或類

? ? ? ? ? ?6.1.2 配置spring配置文件時在 <aop:config> 配置

? ? 6.2 AspectJ

? ? ? ? ? 6.2.1 每個通知都不需要實現接口或類

? ? ? ? ?6.2.2 配置 spring 配置文件是在 <aop:config>的子標簽 <aop:aspect> 中配置的

二 Schema-based 實現步驟

1. 導入jar包


2. 新建通知類

2.1 新建前置通知類,三個參數,agr0:切點方法對象Method 對象。

agr1:切點方法參數,arg2:切點在哪個對象中

public class MyBeforeAdvice implements MethodBeforeAdvice{

? ? ?@Overload

? ? public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable{

? ? ? ? System.out.println("執行前置通知");

????}

}


2.2 新建后置通知類,agr0:切點方法返回值, arg1 切點方法對象,arg2 切點方法參數,arg3 切點方法所在類的對象。

public class MyAfterAdvice implements AfterReturningAdvice{

? ? ?@Overload ? ?

????public void afterReturning(Object arg0,Method arg,1, Object[] arg2, Object arg3) throws Throwable{

? ? ? ? System.out.println("執行后置通知"); ???

?????}

}?


3 配置spring 配置文件

引入 aop 命名空間 ,配置通知類的<bean>? 配置切面

applicationContext.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:aop="http://www.springframework.org/schema/aop"

xsi:schemaLocation="http://www.springframework.org/sc

hema/beans

http://www.springframework.org/schema/beans/spring-be

ans.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop.

xsd">

<!-- 配置通知類對象,在切面中引入 -->

<bean id="mybefore"? ?class="com.chen.advice.MyBeforeAdvice"></bean>

<bean id="myafter"? ?class="com.chen.advice.MyAfterAdvice"></bean>

<!-- 配置切面 -->

<aop:config>

<!-- 配置切點 -->

<aop:pointcut expression="execution(*? com.chen.test.Demo.demo2())"? id="mypoint"/>

<!-- 通知 -->

<aop:advisor advice-ref="mybefore"? pointcut-ref="mypoint"/>

<aop:advisor advice-ref="myafter"? ?pointcut-ref="mypoint"/>

</aop:config>

<!-- 配置 Demo 類,測試使用 ,ioc? 控制反轉特效,把對bean的引用 奪到spring 中去-->

<bean id="demo" class="com.chen.test.Demo"></bean>

</beans>


測試類

public class Test {

????public static void main(String[] args) {

? ? /**

? ? ? ? *通過ioc特性,自己不用創建demo

????*/

?????// Demo demo = new Demo();

????????// demo.demo1();

????????// demo.demo2();

????????// demo.demo3();

????????ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

????????Demo demo = ac.getBean("demo",Demo.class);

????????demo.demo1();

????????demo.demo2();

????????demo.demo3();

????}

}

執行結果


三? 配置異常通知的步驟(AspectJ方式)


1. 只有切點報異常才能出發異常通知,切點也就是 Demo

2. 在 spring 中 有AspectJ 方式提供了異常通知的方法,如果想用 schema-base 實現實現特點的要求自己編寫方法

3. 實現步驟,新建類,在類寫任意名稱的方法

public class MyThrowAdvice{

????public void myexception(Exception e1){

????????System.out.println("執行異常通知"+e1.getMessage());

????}

}


3.1 在spring 配置文件中配置

? ? <aop:aspect> 的ref屬性表示:方法在哪個類中

? ? <aop:xxxx/> 表示什么通知

? ? method:當觸發這個通知時,調用哪個方法

? ? throwing:異常對象名,必須和通知中方法參數名相同(可以不在通知聲明異常對象)

applicationContext.xml

<bean id="mythrow"? class="com.chen.advice.MyThrowAdvice"></bean>

????<aop:config>

????????<aop:aspect ref="mythrow">

????????<aop:pointcut expression="execution(* com.chen.test.Demo.demo1())" id="mypoint"/>

????????<aop:after-throwing method="myexception"? pointcut-ref="mypoint" throwing="e1"/>

????????</aop:aspect>

????</aop:config>

<bean id="demo" class="com.chen.test.Demo"></bean>


四 異常通知(Schema-based方式)

1. 新建一個類,實現throwsAdvice接口,

必須自己寫方法,切必須叫afterThrowing

有兩個參數方式,必須是一個或者4個

異常類型要與切點報的異常類型一致

public class MyThrow implements ThrowsAdvice{

????public void afterThrowing(Exception ex) throws Throwable {

????????System.out.println("執行異常通過-schema-base 方式");

????}

}


在applicationContext.xml 配置

<bean id="mythrow"? class="com.chen.advice.MyThrow"></bean>

????<aop:config>

????????<aop:pointcut expression="execution(* com.chen.test.Demo.demo1())" id="mypoint"/>

????????<aop:advisor advice-ref="mythrow" pointcut-ref="mypoint" />

????</aop:config>

<bean id="demo" class="com.chen.test.Demo"></bean>


五 環繞通知(Schema-based 方式)

1. 把前置通知和后置通知都寫到了一個通知里,組成那個了環繞通知

2.實現步驟,新建一個類實現 MethodInterceptor

public class MyArround implements MethodInterceptor {

????@Override

????public Object invoke(MethodInvocation arg0) throws Throwable {

????????System.out.println("環繞-前置");

????????Object result = arg0.proceed();//放行,調用切點方式

????????System.out.println("環繞-后置");

????????return result;

????}

}


配置 applicationContext.xml

<bean id="myarround" class="com.chen.advice.MyArround"></bean>

????<aop:config>

????<aop:pointcut expression="execution(* com.chen.test.Demo.demo1())" id="mypoint"/>

????<aop:advisor advice-ref="myarround" pointcut-ref="mypoint" />

????</aop:config>

<bean id="demo" class="com.chen.test.Demo"></bean>


六 使用AspectJ 方式實現

1. 新建類,不用實現

? ? 1.1 類中方法名任意

public class MyAdvice {

????public void mybefore(String name1,int age1){

???????System.out.println("前置"+name1 );

????}

????public void mybefore1(String name1){

????????System.out.println("前置:"+name1);

????}

????public void myaftering(){

????????System.out.println("后置 2");

????}

????public void myafter(){

????????System.out.println("后置 1");

????}

????public void mythrow(){

????????System.out.println("異常");

????}

????public Object myarround(ProceedingJoinPoint p) throws Throwable{

? ? ????System.out.println("執行環繞");

? ? ? ? System.out.println("環繞-前置");

? ? ? ? Object result = p.proceed();

????????System.out.println("環繞后置");

????????return result;

}


1.2 配置spring 配置文件

<aop: after> 后置通知,是否出現異常都執行

<aop:after-returning/> 后置通知,只有切點正確執行時執行,

<aop:after/> 和 <aop:after-returning/> 和 <aop: after-throwing/> 執行順序和配置順序相關

?execution() 括號不能擴上,args

中間使用 and 不能使用 && 由 spring 把 and 解析成 &&

args(名稱) 名稱自定義,順序和demo1(參數,參數)對應

<aop:before/> arg-name="名稱" 名稱來源于expression ="" 中args(),名稱必須一樣

args() 有幾個參數,arg-name 里面必須有幾個參數

arg-name="" 里面名稱必須和通知方法參數名對象

<aop:config>

????<aop:aspect ref="myadvice">

????????<aop:pointcut expression="execution(* com.chen.test.Demo.demo1(String,int)) and args(name1,age1)" id="mypoint"/>

????????<aop:pointcut expression="execution(* com.chen.test.Demo.demo1(String)) and args(name1)" id="mypoint1"/>

????????<aop:before method="mybefore" pointcut-ref="mypoint" arg-names="name1,age1"/>

????????<aop:before method="mybefore1" pointcut-ref="mypoint1" arg-names="name1"/>

????</aop:aspect>

</aop:config>

七 使用注解(基于 Aspect)

1. spring 不會自動去尋找注解,必須告訴 spring 哪些包下的類中可能有注解

1.1 引入xmlns:context

<context:component-scan base-package="com.chen.advice"></context:component-scan>

2. @Component

????相當于<bean/>? ?

????如果沒有參數,把類名首字母變小寫,相當于<bean id=""/>

? ? @Component("自定義名稱")

實現步驟

? ? 在spring配置文件中配置注解在哪些包中1.? 然后多個包? 用? ,? 隔開

? ? 在Demo 類中添加@Componet

? ? 在方法中添加@Pointcut("")定義切點

@Component

public class Demo {

????@Pointcut("execution(*com.chen.test.Demo.demo1())")

????public void demo1() throws Exception{

????????// int i = 5/0;

????????System.out.println("demo1");

????}

}


3.3 在通知類中配置

? ? @Component 類被 Spring管理

? ? @Aspect 相當于<aop:aspect/> 表示通知方法在當前類中


@Component

@Aspect

public class MyAdvice {

????@Before("com.chen.test.Demo.demo1()")

????public void mybefore(){

????????System.out.println("前置");

????}

????@After("com.chen.test.Demo.demo1()")

????public void myafter(){

????????System.out.println("后置通知");

????}

????@AfterThrowing("com.chen.test.Demo.demo1()")

? ? public void mythrow(){

????????System.out.println("異常通知");

????}

????@Around("com.chen.test.Demo.demo1()")

????public Object myarround(ProceedingJoinPoint p) throws Throwable{

????????System.out.println("環繞-前置");

????????Object result = p.proceed();

????????System.out.println("環繞-后置");

????return result;

????}

}


九 靜態代理設計模式

1.? 由代理對象代理所有真實對象的功能

????????自己編寫代理類

????????每個代理的功能需要單獨編寫

2靜態代理設計模式的缺點

????????當代理功能比較多時,代理類中方法需要寫很多

十 動態代理

1. 為了解決靜態代理頻繁編寫代理功能缺點

2 分類

? ? ? ? jdk 提供的

? ? ? ? cglib 動態代理

十一? JDK 動態代理

1. 和cglib 動態代理相比

? ? ? ? 優點:jdk自帶,不需要導入額外jar

? ? ? ? 缺點? : 真實對象必須實現接口,利用反射機制,效率不高

2. 使用JDK動態代理是可能出現下面異常

? ? ? ? ? ? 出現原因:希望把接口對象轉換為具體真實對象

異常: java.lang.ClassCastException

十二 cglib 動態代理

1.cglib優點

? ? ? ? 基于字節碼,生成真實對象的子類

? ? ? ? ????運行效率高于JDK動態代理

? ? ? ? 不需要實現接口

? 2 cgilb 缺點

? ? ? ? 非JDK功能,需要導入額外jar

3. 使用spring aop時,只要出現Proxy 和真實對象轉換異常

? ? ? ? 設置為true 使用cglib

? ? ? ? 設置為 false 使用 jdk(默認值)

<aop: aspectj-autoproxyproxy-target-class="true"></aop:aspectj-autoproxy>

?

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,781評論 18 139
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,717評論 18 399
  • 到底是有才華的人容易有所成就,還是有激情的人容易有所成就? 才華是一個人的天賦秉性,與生俱來的某種能力。擁有才華是...
    恒樂哥哥閱讀 632評論 0 1
  • 前言 最近在看YouTube視頻時,里面有自動字幕功能,當時非常激動,字幕很準確;其實YouTube這個功能在20...
    iHTCboy閱讀 72,068評論 7 23
  • 哇塞,我已經有9天沒寫些東西了,實在抱歉,我是個很懶的人,但是我確實想改變這一點,所以我決定每天還是寫些東西,認真...
    巴扎扎閱讀 117評論 0 0