將cglib動態代理思想帶入Android開發
動態代理在Android實際開發中用的並不是很多,但在設計框架的時候用的就比較多了,最近在看J2EE一些東西,像Spring,Hibernate等都有通過動態代理來實現方法增強、方法攔截等需要,通過代理的方式優雅的實現AOP程式設計。我們今天來看看這個代理究竟是什麼樣子,在Android開發中如何使用它,以及將cglib動態代理思想在Android中看看如何實現。
專案地址:MethodInterceptProxy
一、什麼是代理
通常我們說的代理,在生活中就像中介、經紀人的角色。
目標物件/被代理物件 ------ 房主:真正的租房的方法
代理物件 ------- 黑中介:有租房子的方法(呼叫房主的租房的方法)
執行代理物件方法的物件 ---- 租房的人
流程:我們要租房----->中介(租房的方法)------>房主(租房的方法)
抽象:呼叫物件----->代理物件------>目標物件
二、靜態代理
先看看比較常見的靜態代理,也就是裝飾設計模式:
首先建一個Star介面:
public interface Star {
void singSong();
}
然後建Star子類SuperStar
public class SuperStar implements Star {
@Override
public void singSong() {
System.out.println("唱歌啦--------");
}
}
最後我們建立SuperStar的代理類SuperStarProxy
public class SuperStarProxy implements Star {
private Star star;
SuperStarProxy(Star star){
this.star = star;
}
@Override
public void singSong() {
System.out.println("before-------------");
star.singSong();
System.out.println("after-------------");
}
}
public static void main(String[] args) {
Star star = new SuperStarProxy(new SuperStar());
star.singSong();
}
我們將需要代理的物件傳進來生成代理物件,之後只需要使用代理物件來處理相關業務就可以了。
三、動態代理
靜態代理需要為每一個需要代理的類寫一個代理類,為每一個需要代理的方法重寫代理方法,如果有上百個類或者類裡方法很多,那重複的工作量也是很可觀的。JDK提供了動態代理方式,可以簡單理解為在JVM可以在執行時幫我們動態生成一系列的代理類,這樣我們就不需要手寫每一個靜態的代理類了。
final Star star = new SuperStar();
Star st = (Star) Proxy.newProxyInstance(Star.class.getClassLoader(), star.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before---------");
Object object = method.invoke(star, args);
System.out.println("after---------");
return object;
}
});
st.singSong();
newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
引數一:類載入器,動態代理類,執行時建立。一般情況:當前類.class.getClassLoader()
引數二:interfaces:代表與目標物件實現的所有的介面位元組碼物件陣列
引數三:具體的代理的操作,InvocationHandler介面
通過JDK提供的動態代理方式,我們可以很輕鬆的生成代理物件,但通過這種方式實現代理有個很大的限制就是:JDK的Proxy方式實現的動態代理,目標物件必須有介面,沒有介面不能實現jdk版動態代理。
四、cglib
cglib是一個功能強大,高效能的程式碼生成包。它為沒有實現介面的類提供代理,為JDK的動態代理提供了很好的補充。通常可以使用Java的動態代理建立代理,但當要代理的類沒有實現介面或者為了更好的效能,cglib是一個好的選擇。
但是但是但是,一個很致命的缺點是:cglib底層採用ASM位元組碼生成框架,使用位元組碼技術生成代理類,也就是生成的.class檔案,而我們在android中載入的是優化後的.dex檔案,也就是說我們需要可以動態生成.dex檔案代理類,cglib在android中是不能使用的。但後面我們會根據dexmaker框架來仿照動態生成.dex檔案,實現cglib的動態代理功能。
好了,我們先來看下cglib的強大吧~
舉個例子,boss安排要實現一個人員管理的增刪改查功能,那這個簡單,三兩下就搞定:
public class PeopleService {
public void add(){
System.out.println("add-----------");
}
public void delete(){
System.out.println("delete-----------");
}
public void update(){
System.out.println("update-----------");
}
public void select(){
System.out.println("select-----------");
}
}
OK,搞定~但是呢,需求是不斷變化的,過了幾天,boss又發話了,說不是每個人都可以使用這個增刪改查功能的,要指定人員才可以使用,那。。我們就改吧~最直接的方式,在每個方法上都加上判斷條件,但這麼做多少有點太挫了,如果有五十個方法,那我們這麼多方法就要都加一遍,用cglib我們可以這麼做:
final String name = "張si";
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(PeopleService.class);
//目標物件攔截器,實現MethodInterceptor
//Object object為目標物件
//Method method為目標方法
//Object[] args 為引數,
//MethodProxy proxy CGlib方法代理物件
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object object, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
Object obj = null;
if(name.equals("張三")){
obj = proxy.invokeSuper(object, args); ;
}else{
System.out.println("----對不起,您沒有許可權----");
}
return obj;
}
});
PeopleService ps = (PeopleService) enhancer.create();
ps.add();
只需新增一個攔截器,就可以攔截所有增刪改查操作,從切面進行統一管理,程式碼量也不多。
又過了幾天,boss又發話了,我們的增刪改查不是都要有限制,只有查詢才對特定人員有限制,那我們就繼續改嘍~
這個時候我們就可以加入過濾器CallbackFilter:
final String name = "張武";
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(PeopleService.class);
//目標物件攔截器,實現MethodInterceptor
//Object object為目標物件
//Method method為目標方法
//Object[] args 為引數,
//MethodProxy proxy CGlib方法代理物件
MethodInterceptor interceptor = new MethodInterceptor() {
@Override
public Object intercept(Object object, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
Object obj = null;
if(name.equals("張三")){
obj = proxy.invokeSuper(object, args); ;
}else{
System.out.println("----對不起,您沒有許可權----");
}
return obj;
}
};
//NoOp.INSTANCE:這個NoOp表示no operator,即什麼操作也不做,代理類直接呼叫被代理的方法不進行攔截
enhancer.setCallbacks(new Callback[]{interceptor,NoOp.INSTANCE});
enhancer.setCallbackFilter(new CallbackFilter() {
//過濾方法
//返回的值為數字,代表了Callback陣列中的索引位置,要到用的Callback
@Override
public int accept(Method method) {
if(method.getName().equals("select")){
return 0;
}
return 1;
}
});
PeopleService ps = (PeopleService) enhancer.create();
ps.add();
我們沒有修改一行原有的增刪改查程式碼,通過傳遞代理物件的方式輕鬆解決方法攔截、方法增強的業務需求。
但遺憾的是,cglib不支援android平臺。。。那我們就自己實現咯~在dexmaker和cglib-for-android庫的基礎上,修改部分程式碼後形成我們的類似cglib框架 MethodInterceptProxy ,實現上面需求只需這樣寫,和cglib寫法一致:
final String name = "張五";
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(PeopleService.class);
//目標物件攔截器,實現MethodInterceptor
//Object object為目標物件
//Method method為目標方法
//Object[] args 為引數,
//MethodProxy proxy CGlib方法代理物件
MethodInterceptor interceptor = new MethodInterceptor() {
@Override
public Object intercept(Object object, Object[] args, MethodProxy methodProxy) throws Throwable {
Object obj = null;
if(name.equals("張三")){
obj = methodProxy.invokeSuper(object, args); ;
}else{
System.out.println("----對不起,您沒有許可權----");
}
return obj;
}
};
//NoOp.INSTANCE:這個NoOp表示no operator,即什麼操作也不做,代理類直接呼叫被代理的方法不進行攔截
enhancer.setCallbacks(new MethodInterceptor[]{interceptor,NoOp.INSTANCE});
enhancer.setCallbackFilter(new CallbackFilter() {
//過濾方法
//返回的值為數字,代表了Callback陣列中的索引位置,要到用的Callback
@Override
public int accept(Method method) {
if(method.getName().equals("select")){
return 0;
}
return 1;
}
});
PeopleService ps = (PeopleService) enhancer.create();
ps.add();
專案地址:MethodInterceptProxy
相關文章
- CGLib 動態代理CGLib
- Java代理(jdk靜態代理、動態代理和cglib動態代理)JavaJDKCGLib
- 動態代理-cglib分析CGLib
- JDK動態代理和 CGLIB 代理JDKCGLib
- JDK動態代理和CGLib代理JDKCGLib
- 3.靜態代理&動態代理&CGlibCGLib
- 代理模式詳解:靜態代理、JDK動態代理與Cglib動態代理模式JDKCGLib
- (轉)Java動態代理與CGLib代理JavaCGLib
- CGlib動態代理複習CGLib
- 靜態代理和動態代理(jdk/cglib)詳解JDKCGLib
- spring aop原理 JDK動態代理和CGLIB動態代理SpringJDKCGLib
- Java進階之 JDK動態代理與Cglib動態代理JavaJDKCGLib
- Java動態代理(JDK和cglib)JavaJDKCGLib
- 你必須會的 JDK 動態代理和 CGLIB 動態代理JDKCGLib
- CGLib動態代理原理及實現CGLib
- 【深度思考】聊聊CGLIB動態代理原理CGLib
- 聊聊cglib動態代理遇到的坑CGLib
- CGlib動態代理-簡單介紹CGLib
- 設計模式之cglib動態代理設計模式CGLib
- cglib動態代理和jdk動態代理的區別與應用CGLibJDK
- 由《尋秦記》說代理模式(靜態,動態,CGLib)模式CGLib
- 動態代理jdk和cglib的區別JDKCGLib
- 最詳細的代理講解--JDK動態代理和cglib代理JDKCGLib
- Spring動態代理的生成-如何判斷是使用JDK動態代理還是CGlib代理SpringJDKCGLib
- 基於 CGLIB 庫的動態代理機制CGLib
- 動態代理jdk的Proxy與spring的CGlibJDKSpringCGLib
- JDK 和 CGLib 實現動態代理和區別JDKCGLib
- Java JDK Proxy和CGLib動態代理示例講解JavaJDKCGLib
- Jmh測試JDK,CGLIB,JAVASSIST動態代理方式的效能JDKCGLibJava
- 面試造火箭系列,栽在了cglib和jdk動態代理面試CGLibJDK
- Java動態代理 jdk和cglib的實現比較JavaJDKCGLib
- 設計模式【3.3】-- CGLIB動態代理原始碼解讀設計模式CGLib原始碼
- SSM-Spring-10:Spring中cglib動態代理SSMSpringCGLib
- 【4】JDK和CGLIB生成動態代理類的區別JDKCGLib
- Android 動態代理以及利用動態代理實現 ServiceHookAndroidHook
- CGLIB代理CGLib
- SpringAOP中JDK和CGLib動態代理哪個更快?SpringJDKCGLib
- 【趣味設計模式系列】之【代理模式3--Cglib動態代理原始碼解析】設計模式CGLib原始碼