Java動態代理JDK與Cglib

一.什麼是代理

在實現委託類的功能的前提下,增加代理類特有的功能

二.常用代理方式

靜態代理:由程序員自己創建的事實存在的代理類,在程序運行前就已經存在了,缺點也十分明顯:大量的靜態代理,會使得類的規模龐雜,難於維護

動態代理:程序運行時纔會產生

三.靜態代理分析與實例

靜態代理模式必須元素

1.Service接口——用於定義業務

2.ServiceImp類——實現具體業務

3.Proxy類——代理類,調用ServiceImp實現具體業務,並且調用自己的業務

具體案例,通過靜態代理實現車票代售服務

1.Service接口

public interface TicketService {
	//車票查詢
	public void queryTicket();
	//車票售賣
	public void sellTicket();
}

2.ServiceImp類

public class Station implements TicketService{
	public void queryTicket() {
		System.out.println("query ticket..");
	}
	public void sellTicket() {
		System.out.println("sell ticket..");
	}

}

3.Proxy類

public class ProxyStation implements TicketService{
	private Station ts;

	public ProxyStation(Station ts) {
		this.ts = ts;
	}

	@Override
	public void queryTicket() {
		System.out.println("proxy to do");
		ts.queryTicket();
	}

	@Override
	public void sellTicket() {
		System.out.println("proxy to do");
		ts.sellTicket();
	}

四.動態代理分析與實例

動態代理類的字節碼在程序運行時通過java反射機制動態生成,無需程序員手動編寫,這樣就簡化了編程工作,提高了軟件系統擴展與維護性能

在這裏簡單介紹常用的兩種動態代理方式——JDK與Cglib

        1.JDK(通過接口實現代理)

具體實現流程

1.獲取ServiceImp上的所有接口

2.動態創建Proxy類的字節碼並且轉換爲class

3.創建InvocationHandler的實例以處理Proxy所有方法調用

4.Proxy以創建的InvocationHandler對象爲參數實例化一個Proxy

        在這裏引入了一個新的類InvocationHandler

      InvocationHandler的存在意義:不同於靜態代理,對於每個接口方法都重寫,然後去調用具體實現類中的方法,而是將所有的方法都交給了InvocationHandler管理,讓其調用具體實現類的對應業務方法,所以JDK實現動態代理的缺點也很明顯,只能代理接口定義的方法

       案例實現

1.Service接口

public interface TicketService {
	//車票查詢
	public void queryTicket();
	//車票售賣
	public void sellTicket();
}

2.ServiceImp類

public class Station implements TicketService{
	public void queryTicket() {
		System.out.println("query ticket..");
	}
	public void sellTicket() {
		System.out.println("sell ticket..");
	}

}

3.Proxy類

public class TicketStationProxy implements InvocationHandler{
	private TicketStation ticketStation;
	

	public TicketStationProxy(TicketStation ticketStation) {
		this.ticketStation = ticketStation;
	}


	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("going to "+method.getName());
		method.invoke(ticketStation, args);
		return null;
	}

}


4.Test測試

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		TicketStation ts = new TicketStation();
		TicketStationProxy proxy = new TicketStationProxy(ts);
		ClassLoader classLoader = ts.getClass().getClassLoader();
		Class<?>[] interFace = ts.getClass().getInterfaces();
		TicketService tsProxy = (TicketService) Proxy.newProxyInstance(classLoader, interFace, proxy);
		tsProxy.queryTicket();
	}

}


2.Cglib實現動態代理流程與分析

1.查找委託類上所有非final的public方法

2.將獲取方法轉換成對應的字節碼,組合並且生成對應的class

3.通過實現MethodInterceptor接口來處理proxy上對應的所有業務方法

MethodInterceptor作用類似InvocationHandler


案例分析

1.Service委託類

public class Station {
	public void queryTicket() {
		System.out.println("query ticket..");
	}
	public void sellTicket() {
		System.out.println("sell ticket..");
	}

}

2.代理類

代理類中包含一個返回代理對象的方法,具體實現方法

1.創建一個Enhancer對象,設置Enhancer

public class TicketCg implements MethodInterceptor { 
	private TicketStation ts;
	public Object getInstance(TicketStation ts) {
		this.ts = ts;
		Enhancer en = new Enhancer();
		en.setSuperclass(this.ts.getClass());
		en.setCallback(this);
		return en.create();
	}

	@Override
	public Object intercept(Object obj, Method arg1, Object[] arg2,
			MethodProxy arg3) throws Throwable {
		System.out.println("Cglib going to "+arg1.getName());
		// TODO Auto-generated method stub
		arg1.invoke(ts, arg2);
		return obj;
	}

}


3.Test

public class CglibTest {
	public static void main(String[] args) throws InterruptedException{
		TicketStation ts = new TicketStation();
		TicketCg tc = new TicketCg();
		TicketStation proxy = (TicketStation) tc.getInstance(ts);
		proxy.queryTicke();
	}
}


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