日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

【Spring】Spring第二天 - AOP 详解、动态代理设计模式(JDK和cglib)

發布時間:2024/2/28 javascript 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Spring】Spring第二天 - AOP 详解、动态代理设计模式(JDK和cglib) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一.AOP

AOP 和 Filter 能夠實現的 功能相似。

AOP 和 Filter 的區別:

  • AOP攔截的是類中方法(切點),只要方法能夠被Spring管理,那么這個方法就能夠被攔截。
  • Filter攔截的是請求。

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

2.英文名稱:(Aspect Oriented Programming)

3.正常程序執行流程都是縱向執行流程
3.1 又叫面向切面編程,在原有縱向執行流程中添加橫切面
3.2 不需要修改原有程序代碼
3.2.1 高擴展性
3.2.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 新建前置通知類
2.1.1 arg0: 切點方法對象Method 對象
2.1.2 arg1: 切點方法參數
2.1.3 arg2:切點在哪個對象中

public class MyBeforeAdvice implements MethodBeforeAdvice {@Overridepublic void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {System.out.println("執行前置通知");} }

2.2 新建后置通知類
2.2.1 arg0: 切點方法返回值
2.2.2 arg1:切點方法對象
2.2.3 arg2:切點方法參數
2.2.4 arg3:切點方法所在類的對象

public class MyAfterAdvice implements AfterReturningAdvice {@Overridepublic void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {System.out.println("執行后置通知");} }

3. 配置 spring 配置文件
3.1 引入 aop 命名空間
3.2 配置通知類的<bean>
3.3 配置切面
3.4 * 通配符,匹配任意方法名,任意類名,任意一級包名
(下面圖中第一個*表示返回值類型,也就是我們不關心方法返回值類型。圖上的解釋‘聲明通配符’是錯誤的解釋。)

3.5 如果希望匹配任意方法參數(..)

<?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/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 配置通知類對象,在切面中引入 --><bean id="mybefore" class="com.bjsxt.advice.MyBeforeAdvice"></bean><bean id="myafter" class="com.bjsxt.advice.MyAfterAdvice"></bean><!-- 配置切面 --><aop:config><!-- 配置切點 --><aop:pointcut expression="execution(*com.bjsxt.test.Demo.demo2())" id="mypoint" /><!-- 通知 --><aop:advisor advice-ref="mybefore" pointcut-ref="mypoint" /><aop:advisor advice-ref="myafter" pointcut-ref="mypoint" /></aop:config><!-- 配置Demo 類,測試使用 --><bean id="demo" class="com.bjsxt.test.Demo"></bean> </beans>

4. 編寫測試代碼

public class Test {public static void main(String[] args) {ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");Demo demo = ac.getBean("demo", Demo.class);demo.demo1();demo.demo2();demo.demo3();} }
  • 運行結果:

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

    1. 只有當切點報異常, 才能觸發異常通知

    2. 在spring 中有AspectJ 方式提供了異常通知的辦法.
    2.1 如果希望通過schema-base 實現需要按照特定的要求自己編寫方法.

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

    public class MyThrowAdvice {public void myexception(Exception e1) {System.out.println("執行異常通知" + e1.getMessage());} }

    3.2 在spring 配置文件中配置
    3.2.1 <aop:aspect>的 ref 屬性表示:方法在哪個類中.
    3.2.2 <aop: xxxx/> 表示什么通知
    3.2.3 method: 當觸發這個通知時,調用哪個方法
    3.2.4 throwing: 異常對象名,必須和通知中方法參數名相同(可以不在通知中聲明異常對象)

    <bean id="mythrow" class="com.bjsxt.advice.MyThrowAdvice"></bean><aop:config><aop:aspect ref="mythrow"><aop:pointcut expression="execution(*com.bjsxt.test.Demo.demo1())" id="mypoint" /><aop:after-throwing method="myexception" pointcut-ref="mypoint" throwing="e1" /></aop:aspect></aop:config><bean id="demo" class="com.bjsxt.test.Demo"></bean>

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

    1. 新建一個類實現throwsAdvice 接口
    1.1 必須自己寫方法,且必須叫afterThrowing
    1.2 有兩種參數方式
    1.2.1 必須是 1個4個
    1.3 異常類型要與切點報的異常類型一致

    public class MyThrow implements ThrowsAdvice { // public void afterThrowing(Method m, Object[] args, Object target, Exception ex) { // System.out.println("執行異常通知"); // }public void afterThrowing(Exception ex) throws Throwable {System.out.println("執行異常通過-schema-base 方式 ");} }

    2. 在ApplicationContext.xml 配置

    <bean id="mythrow"class="com.bjsxt.advice.MyThrow"></bean><aop:config><aop:pointcut expression="execution(*com.bjsxt.test.Demo.demo1())" id="mypoint"/><aop:advisor advice-ref="mythrow" pointcut-ref="mypoint" /></aop:config><bean id="demo" class="com.bjsxt.test.Demo"></bean>

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

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

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

    public class MyArround implements MethodInterceptor {@Overridepublic Object invoke(MethodInvocation arg0) throws Throwable {System.out.println("環繞-前置");Object result = arg0.proceed();// 放行,調用切點方式System.out.println("環繞-后置");return result;} }

    2.2 配置 applicationContext.xml

    <bean id="myarround" class="com.bjsxt.advice.MyArround"></bean><aop:config><aop:pointcut expression="execution(* com.bjsxt.test.Demo.demo1())" id="mypoint" /><aop:advisor advice-ref="myarround" pointcut-ref="mypoint" /></aop:config><bean id="demo" class="com.bjsxt.test.Demo"></bean>

    六.使用AspectJ 方式實現

    1. 新建類,不用實現
    1.1 類中方法名任意

    // 本示例非sxt原示例,我本地稍微修改了下 package com.bjsxt.advice;import org.aspectj.lang.ProceedingJoinPoint;public class MyAdvice {public void aopBefFunc2arg(String name, int age) {System.out.println("MyAdvice.aopBefFunc2arg()");System.out.println("前置" + name);}public void aopBefFunc1arg(String name) {System.out.println("MyAdvice.aopBefFunc1arg()");System.out.println("前置:" + name);}public void aopAfteringFunc0arg() {System.out.println("MyAdvice.aopAfteringFunc0arg()");System.out.println("后置2");}public void aopAfterFunc0arg() {System.out.println("MyAdvice.aopAfterFunc0arg()");System.out.println("后置1");}public void aopThrowFunc() {System.out.println("MyAdvice.aopThrowFunc()");System.out.println("異常");}public Object myarround(ProceedingJoinPoint p) throws Throwable {System.out.println("MyAdvice.myarround()");System.out.println("before Object result = p.proceed()");Object result = p.proceed();System.out.println("after Object result = p.proceed()");return result;} }

    1.2 配置 spring 配置文件
    1.2.1 <aop:after/> 后置通知,是否出現異常都執行
    1.2.2 <aop:after-returing/> 后置通知,只有當切點正確執行時執行
    1.2.3 <aop:after/> 和<aop:after-returing/> 和<aop:after-throwing/>執行順序和配置順序有關
    1.2.4 execution() 括號不能擴上args
    1.2.5 中間使用 and 不能使用 && ,由 spring 把 and 解析成 &&
    1.2.6 args(名稱) 名稱自定義的.順序和demo1(參數,參數)對應
    1.2.7 <aop:before/>, arg-names=” 名稱” 名稱來源于expression=”” 中args(),名稱必須一樣
    1.2.7.1 args() 有幾個參數,arg-names 里面必須有幾個參數
    1.2.7.2 arg-names=”” 里面名稱必須和通知方法參數名對應

    // 本示例非sxt原示例,稍微修改了下 <?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/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><bean id="demo" class="com.bjsxt.test.Demo"></bean><bean id="myadvice" class="com.bjsxt.advice.MyAdvice"></bean><aop:config><!-- 配置切面 --><aop:aspect ref="myadvice"><!-- 配置切點 --><aop:pointcutexpression="execution(* com.bjsxt.test.Demo.demoMethod(String,int)) and args(name,age)"id="pointcut_2_arg" /><aop:pointcutexpression="execution(* com.bjsxt.test.Demo.demoMethod(String)) and args(name)"id="pointcut_1_arg" /><aop:pointcutexpression="execution(* com.bjsxt.test.Demo.demoMethod())"id="pointcut_0_arg" /><aop:pointcutexpression="execution(* com.bjsxt.test.Demo.*(..))" id="pointcut_all" /><aop:before method="aopBefFunc2arg"pointcut-ref="pointcut_2_arg" arg-names="name,age" /><aop:before method="aopBefFunc1arg"pointcut-ref="pointcut_1_arg" arg-names="name" /><aop:after method="aopAfterFunc0arg"pointcut-ref="pointcut_0_arg" /><aop:after method="aopAfterFunc0arg"pointcut-ref="pointcut_all" /><!-- <aop:after method="myafter" pointcut-ref="mypoint1" arg-names="name"/> --><!-- <aop:after method="myafter" pointcut-ref="mypoint"/> --><!-- <aop:after-returning method="myaftering" pointcut-ref="mypoint"/> --><!-- <aop:after-throwing method="mythrow" pointcut-ref="mypoint"/> --><!-- <aop:around method="myarround" pointcut-ref="mypoint"/> --></aop:aspect></aop:config> </beans>

    七. 使用注解(基于Aspect)

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

    <context:component-scanbase-package="com.bjsxt.advice"></context:component-scan>

    2. @Component
    2.1 相當于<bean/>
    2.2 如果沒有參數,把類名首字母變小寫,相當于<bean id=””/>
    2.3 @Component(“自定義名稱”)

    2. 實現步驟:
    3.1 在 spring 配置文件中設置注解在哪些包中

    <context:component-scan base-package="com.bjsxt.advice,com.bjsxt.test"></context:component-scan>

    3.2 在 Demo 類中添加@Componet
    3.2.1 在方法上添加@Pointcut(“”) 定義切點

    @Component public class Demo {@Pointcut("execution(* com.bjsxt.test.Demo.demo1())")public void demo1() throws Exception{// int i = 5/0;System.out.println("demo1");} }

    3.3 在通知類中配置
    3.3.1 @Component 類被spring 管理
    3.3.2 @Aspect 相當于<aop:aspect/>表示通知方法在當前類中

    @Component @Aspect public class MyAdvice {@Before("com.bjsxt.test.Demo.demo1()")public void mybefore() {System.out.println("前置");}@After("com.bjsxt.test.Demo.demo1()")public void myafter() {System.out.println("后置通知");}@AfterThrowing("com.bjsxt.test.Demo.demo1()")public void mythrow() {System.out.println("異常通知");}@Around("com.bjsxt.test.Demo.demo1()")public Object myarround(ProceedingJoinPoint p) throws Throwable {System.out.println("環繞-前置");Object result = p.proceed();System.out.println("環繞-后置");return result;} }

    八.代理設計模式

    1. 設計模式:前人總結的一套解決特定問題的代碼.

    2. 代理設計模式優點:
    2.1 保護真實對象
    2.2 讓真實對象職責更明確.
    2.3 擴展

    3. 代理設計模式
    3.1 真實對象.(老總)
    3.2 代理對象(秘書)
    3.3 抽象對象(抽象功能),談小目標


    九. 靜態代理設計模式

    1. 由代理對象代理所有真實對象的功能.
    1.1 自己編寫代理類
    1.2 每個代理的功能需要單獨編寫

    2. 靜態代理設計模式的缺點:
    2.1 當代理功能比較多時,代理類中方法需要寫很多.


    十. 動態代理

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

    2. 分類:
    2.1 JDK 提供的
    2.2 cglib 動態代理


    十一. JDK 動態代理

    1. 和cglib 動態代理對比
    1.1 優點:jdk 自帶,不需要額外導入jar
    1.2 缺點:
    1.2.1 真實對象必須實現接口
    1.2.2 利用反射機制.效率不高.

    2. 使用JDK 動態代理時可能出現下面異常
    2.1 出現原因:希望把接口對象轉換為具體真實對象


    十二: cglib 動態代理

    1. cglib 優點:
    1.1 基于字節碼,生成真實對象的子類.
    1.1.1 運行效率高于JDK 動態代理.
    1.2 不需要實現接口

    2. cglib 缺點:
    2.1 非JDK 功能,需要額外導入jar

    3. 使用 spring aop 時,只要出現 Proxy 和真實對象轉換異常
    3.1 設置為true 使用cglib
    3.2 設置為false 使用jdk(默認值)

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

    總結

    以上是生活随笔為你收集整理的【Spring】Spring第二天 - AOP 详解、动态代理设计模式(JDK和cglib)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。