Spring的動態代理有兩種:一是JDK的動態代理;另一個是cglib動態代理(通過修改字節碼來實現代理)。
今天主要討論JDK動態代理的方式。
1 AOP各種的實現
AOP就是面向切面編程,我們可以從幾個層面來實現AOP。
在編譯器修改源代碼,在運行期字節碼加載前修改字節碼或字節碼加載後動態創建代理類的字節碼,以下是各種實現機制的比較。
2 AOP的實現機制
本章節將詳細介紹AOP有各種實現機制。
2.1 動態代理
Java在JDK1.3後引入的動態代理機制,使我們可以在運行期動態的創建代理類。使用動態代理實現AOP需要有四個角色:被代理的類,被代理類的接 口,織入器,和InvocationHandler,而織入器使用接口反射機制生成一個代理類,然後在這個代理類中織入代碼。被代理的類是AOP裏所說的 目標,InvocationHandler是切面,它包含了Advice和Pointcut。
public interface MyDao {
String getName();
}
public class MydaoImpl implements MyDao {
@Override
public String getName() {
// TODO Auto-generated method stub
System.out.println("this is my daoimpl");
return "ok";
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyProxy implements InvocationHandler {
Object obj = null;
public MyProxy(Object obj) {
super();
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("this is method before");
Object result = method.invoke(this.obj, args);
System.out.println("this is method after");
return result;
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyDao dao = new MydaoImpl();
// 獲得被代理類的類加載器,使得JVM能夠加載並找到被代理類的內部結構,以及已實現的interface
ClassLoader loader = dao.getClass().getClassLoader();
// 獲得被代理類已實現的所有接口interface,使得動態代理類的實例
Class<?>[] interfaces = dao.getClass().getInterfaces();
// 用被代理類的實例創建動態代理類的實例,用於真正調用處理程序
InvocationHandler handler = new MyProxy(dao);
/*
* loader : 被代理類的類加載器 interfaces :被代理類已實現的所有接口,而這些是動態代理類要實現的接口列表 handler
* : 用被代理類的實例創建動態代理類的實例,用於真正調用處理程序
*
* return :返回實現了被代理類所實現的所有接口的Object對象,即動態代理,需要強制轉型
*/
// 獲得代理的實例
MyDao proxy = (MyDao) Proxy.newProxyInstance(loader, interfaces,
handler);
proxy.getName();
// 打印出該代理實例的名稱
System.out.println(proxy.getClass().getName());
}
}