一.什麼是代理
在實現委託類的功能的前提下,增加代理類特有的功能
二.常用代理方式
靜態代理:由程序員自己創建的事實存在的代理類,在程序運行前就已經存在了,缺點也十分明顯:大量的靜態代理,會使得類的規模龐雜,難於維護
動態代理:程序運行時纔會產生
三.靜態代理分析與實例
靜態代理模式必須元素
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;
}
}
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;
}
}
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();
}
}