(转)java动态代理与aop
生活随笔
收集整理的這篇文章主要介紹了
(转)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文件的格式和指令集都很熟悉。
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的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 应用程序无法正常启动0xc000007b
- 下一篇: (转)使用IDEA将普通MAVEN项目转