AOP的底層實現

 

 

一、Srping框架的AOP技術底層也是採用的代理技術,代理的方式提供了兩種

二、代理模式

1、jdk動態代理

2、CGLIB字節碼增強


一、Srping框架的AOP技術底層也是採用的代理技術,代理的方式提供了兩種

    1. 基於JDK的動態代理

         必須是面向接口的,只有實現了具體接口的類才能生成代理對象

 

    2. 基於CGLIB動態代理

         對於沒有實現了接口的類,也可以產生代理,產生這個類的子類的方式

 

2. Spring的傳統AOP中根據類是否實現接口,來採用不同的代理方式

    1. 如果實現類接口,使用JDK動態代理完成AOP

    2. 如果沒有實現接口,採用CGLIB動態代理完成AOP

二、代理模式

Proxy Pattern(即:代理模式),23種常用的面向對象軟件的設計模式之一

代理模式的定義:爲其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。

優點:

(1).職責清晰

真實的角色就是實現實際的業務邏輯,不用關心其他非本職責的事務,通過後期的代理完成一件完成事務,附帶的結果就是編程簡潔清晰。

(2).代理對象可以在客戶端和目標對象之間起到中介的作用,這樣起到了的作用和保護了目標對象的作用。

(3).高擴展性

結構

一個是真正的你要訪問的對象(目標類),另一個是代理對象,真正對象與代理

對象實現同一個接口,先訪問代理類再訪問真正要訪問的對象。

代理模式簡單案例

1、jdk動態代理

Java.lang.reflect.Proxy類可以直接生成一個代理對象

Proxy.newProxyInstance():產生代理類的實例。僅能代理實現至少一個接口的類

       ClassLoader:類加載器。固定寫法,和被代理類使用相同的類加載器即可。

       Class[] interface:代理類要實現的接口。固定寫法,和被代理類使用相同的接口即可。

       InvocationHandler:策略(方案)設計模式的應用。如何代理?

 

InvocationHandler中的invoke方法:調用代理類的任何方法,此方法都會執行   

         Object proxy:代理對象本身的引用。一般用不着。

         Method method:當前調用的方法。

         Object[] args:當前方法用到的參數

目標類接口:

public interface WorkInter {
	void workInDay(double money);
	void workInNight(double money);
}

目標類:

public class Worker implements WorkInter{

	@Override
	public void workInDay(double money) {
		System.out.println("workInDay");
		
	}
	@Override
	public void workInNight(double money) {
		System.out.println("workInNight");
	}
}

代理類:

public class JdkProxy {
	@Test
	public void run() {
		WorkInter proxy = (WorkInter) Proxy.newProxyInstance(Worker.class.getClassLoader(), Worker.class.getInterfaces(), new InvocationHandler() {
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

				System.out.println("中介費"+((double)args[0])/2);
				Object invoke = method.invoke(Worker.class.newInstance(), args);
				
				System.out.println("下班");
				return invoke;
			}
		});
		proxy.workInDay(500);
		proxy.workInNight(1000);
	}
}

執行結果:

2、CGLIB字節碼增強

核心類:Enhancer

  1. 沒有接口,只有實現類。
  2. 採用字節碼增強框架 cglib,在運行時 創建目標類的子類,從而對目標類進行增強。

實現步驟:

  1. 獲得代理類的核心類Enhancer對象
  2. 設置父類(目標類),setSuperclass()方法,底層是創建目標類的子類
  3. 設置回調函數enhancer.setCallback(new MethodInterceptor())
  4. 創建代理對象 create()方法

目標類:

public class Worker{
	public void workInDay(double money) {
		System.out.println("workInDay");
		
	}
	public void workInNight(double money) {
		System.out.println("workInNight");
	}
}

代理類:

public class WorkerProxy {
	@Test
	public void run() {
			Enhancer enhancer=new Enhancer();
			//2.設置父類(目標類),setSuperclass()方法,底層是創建目標類的子類
			enhancer.setSuperclass(Worker.class);
			//3.設置回調函數enhancer.setCallback(new MethodInterceptor()) 
			
			enhancer.setCallback(new MethodInterceptor() {
				    *//**
				 * Object object:代理對象
				 * Method method:目標類的方法
				 * Object[] args:方法的形參
				 * MethodProxy methodProxy:方法的代理對象
				 * 
				 *//*
				@Override
				public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
					// TODO Auto-generated method stub
					//開啓事務
					//前置通知
					
					System.out.println("代理收取費用"+ (double)args[0]/2);
					//執行目標方法,需要目標類實例
					Object invoke = method.invoke(Worker.class.newInstance(), (double)args[0]/2);
					
					//後置通知
					
					System.out.println("go  home~~~~~");
					return invoke;
				}
			});
			
			//4.創建代理對象 create()方法
			Worker workerPeoxy = (Worker) enhancer.create();
			
			workerPeoxy.workInDay(500);
			workerPeoxy.workInNight(1000);
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章