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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

(转)java动态代理与aop

發布時間:2023/12/3 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (转)java动态代理与aop 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自: Java 動態代理與AOP - 如果的事 - 博客園動態代理與AOP 代理模式 代理模式給某一個目標對象(target)提供代理對象(proxy),并由代理對象控制對target對象的引用。 模式圖: 代理模式中的角色有: 抽象對象角色(Abstrachttps://www.cnblogs.com/chenny7/p/11201010.html


【1】代理模式

/*** 抽象對象角色*/ abstract class AbstractObject {public abstract void operation(); } /*** 目標對象*/ class TargetObject extends AbstractObject {public void operation() {System.out.println("Do Something!");} } /*** 代理對象*/ public class ProxyObject extends AbstractObject {TargetObject targetObject = new TargetObject();@Overridepublic void operation() {System.out.println("do sth before");targetObject.operation();System.out.println("do sth after");}public static void main(String[] args) {new ProxyObject().operation();} }

代理模式中的角色有:

  • 抽象對象角色(AbstractObject):聲明了目標對象和代理對象的共同接口,這樣依賴在任何可以使用目標對象的地方都可以使用代理對象。
  • 目標對象角色(RealObject):定義了代理對象所代表的目標對象。???
  • 代理對象角色(ProxyObject):代理對象內部含有目標對象的引用,從而可以在任何時候操作目標對象;代理對象提供一個與目標對象相同的接口,以便可以在任何時候替代目標對象。代理對象通常在客戶端調用傳遞給目標對象之前或者之后,執行某個操作,而不是單純的將調用傳遞給目標對象。

【2】靜態代理與動態代理

按照代理類的創建時期,可分為靜態代理和動態代理:

  • 靜態代理:由程序員創建代理類或特定工具自動生成源代碼再對其編譯。在程序運行前代理類的.class文件就已經存在了。
  • 動態代理:在程序運行時運用反射機制動態創建而成。

【2.1】靜態代理

/*** 會飛接口*/ interface Flyable {void fly(long ms); } /*** 會飛的鳥*/ class Bird implements Flyable {@Overridepublic void fly(long ms) {System.out.println("bird is flying.");try {Thread.sleep(ms);} catch (Exception e ) {System.out.println("bird睡眠異常");}} } /*** 會飛的風箏*/ class Kite implements Flyable {@Overridepublic void fly(long ms) {System.out.println("kite is flying.");try {Thread.sleep(ms);} catch (Exception e ) {System.out.println("kite 睡眠異常");}} } /*** 靜態代理*/ public class StaticProxy implements Flyable {private Flyable flyable;public StaticProxy(Flyable flyable) {this.flyable = flyable;}@Overridepublic void fly(long ms) {System.out.println("before fly");flyable.fly(ms);System.out.println("after fly");}public static void main(String[] args) {new StaticProxy(new Kite()).fly(1000);new StaticProxy(new Bird()).fly(1000);} }

靜態代理缺點:

  • 若接口? Flyable 增加一個方法,則目標對象(接口實現類)與代理類全都需要增加方法實現,全都需要修改代碼;

【2.2】動態代理

/*** 動態代理*/ public class DynamicProxy implements InvocationHandler {private Object targetObject;public Object newProxyInstance(Object targetObject) {this.targetObject = targetObject;return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("before invoke");proxy = method.invoke(targetObject, args);System.out.println("before after");return proxy;}public static void main(String[] args) {DynamicProxy dProxy = new DynamicProxy();// 會飛的鳥Flyable bird = (Flyable)dProxy.newProxyInstance(new Bird());bird.fly(1000);// 風箏Flyable kite = (Flyable)dProxy.newProxyInstance(new Kite());kite.fly(1000);} }

顯然, 動態代理對象不需要實現目標對象接口,但目標對象一定要實現接口,否則不能使用代理;


【3】cglib 代理

1)應用場景:

  • 有的時候,目標對象可能只是一個單獨的對象,并沒有實現任何的接口,這個時候,我們就可以使用目標對象子類的方式實現代理,這種代理方式就是:Cglib代理,也叫做子類代理,它是在內存中構件一個子類對象,從而實現對目標對象的功能拓展。

2)cglib 介紹

  • Cglib是強大的高性能的代碼生成包,它可以在運行期間拓展Java類與實現Java接口。它廣泛的被許多AOP的框架使用,例如Spring AOP和synaop,為他們提供方法的interception(攔截)。
  • Cglib包的底層是通過使用一個小而快的字節碼處理框架ASM來轉換字節碼并生成新的類,不鼓勵直接只使用ASM,因為它要求你必須對JVM內部結構,包括class文件的格式和指令集都很熟悉。
class Plane {public void fly(long ms) {System.out.println("plane is flying");try {Thread.sleep(ms);} catch(Exception e) {System.out.println("plane睡眠異常");}} } public class CglibProxy implements MethodInterceptor {private Object target;public CglibProxy(Object target) {this.target = target;}public Object getProxyInstance() {Enhancer enhancer = new Enhancer(); // 1 實例化工具類enhancer.setSuperclass(this.target.getClass()); // 設置父類對象enhancer.setCallback(this); // 設置回調函數return enhancer.create(); // 創建子類,也就是代理對象}// 攔截器方法@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("before invoke");Object returnValue = method.invoke(target, objects);System.out.println("after invoke");return returnValue;}public static void main(String[] args) {CglibProxy cglibProxy = new CglibProxy(new Plane());Plane plane = (Plane)cglibProxy.getProxyInstance();plane.fly(1000);} }

maven pom.xml?

<!-- https://mvnrepository.com/artifact/cglib/cglib --><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version></dependency>

【4】 spring aop

1)Spring在新版本中對AOP功能進行了增強,體現在這么幾個方面:

  • ??? 在XML配置文件中為AOP提供了aop命名空間
  • ??? 增加了AspectJ切點表達式語言的支持
  • ??? 可以無縫地集成AspectJ

2)如何使用 引介切面(Introduction Advisor)為一個現有對象添加任何接口的實現:

2.1)定義兩個接口及其實現類,包括 服務員與售貨員;

public class SpringAopDef { } interface Waiter { // 服務員接口void greetTo(String client);void serveTo(String client); } class NaiveWaiter implements Waiter { // 服務員實現類public void greetTo(String client) {System.out.println("NaiveWaiter greet to " + client);}public void serveTo(String client) {System.out.println("NaiveWaiter serve to " + client);} } interface Seller {// 售貨員接口int sell(String goods, String client); } class SmartSeller implements Seller { // 售貨員實現類public int sell(String goods, String client) {System.out.println("a smart seller sells " + goods + " to " + client);return 100;} }

2.2)下一步,我們想讓 服務員充當售貨員角色,可以賣東西;

引入切面:

@Aspect public class EnableSellerAspect {@DeclareParents(value="com.swjtu.mybatis.proxy.springaop.NaiveWaiter" // 切點-目標類, defaultImpl = SmartSeller.class) // 增強類public Seller seller; // 增強類接口 }

maven pom 引入spring依賴

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.swjtu.mybatis</groupId><artifactId>MybatisHello2</artifactId><version>0.0.1-SNAPSHOT</version><properties><spring.version>5.2.0.RELEASE</spring.version></properties> ................. <dependencies><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.9.4</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency><!-- Spring Dependencies --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency></dependencies>

beans.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:context="http://www.springframework.org/schema/context"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-4.0.xsdhttp://www.springframework.org/schema/context/http://www.springframework.org/schema/context/spring-context.xsd"><aop:aspectj-autoproxy/><bean id="waiter" class="com.swjtu.mybatis.proxy.springaop.NaiveWaiter"/><bean class="com.swjtu.mybatis.proxy.springaop.EnableSellerAspect"/><!-- 定義切面 --><bean id="testBeforeAdvice" class="com.swjtu.mybatis.proxy.springaop.advice.TestBeforeAdvice"/><aop:config proxy-target-class="true"><aop:advisor advice-ref="testBeforeAdvice" pointcut="execution(* com..*.Waiter.greetTo(..))"/></aop:config></beans>

切面如下:

public class TestBeforeAdvice implements MethodBeforeAdvice {@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {System.out.println("before invoke");System.out.println("do busi");System.out.println("after invoke");} }

當調用 Waiter.greetTo() 方法會調用 before 通知;

springaop 測試用例入口:

public class SpringAopMain {public static void main(String[] args) {// 獲取上下文環境ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");Waiter waiter = (Waiter)context.getBean("waiter"); // 從上下文中獲取bean// 調用服務員原有方法waiter.greetTo("zhangsan");waiter.serveTo("zhangsan");// 通過切面已經將 Waiter 實現了 Seller 接口,所以可以強制轉換Seller seller = (Seller) waiter;seller.sell("apple", "zhangsan");} } // spring aop 打印日志 before invoke do busi after invoke NaiveWaiter greet to zhangsan NaiveWaiter serve to zhangsan a smart seller sells apple to zhangsan

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的(转)java动态代理与aop的全部內容,希望文章能夠幫你解決所遇到的問題。

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