今天國慶節第三天,學習複習spring的實現AOP思想所使用的的原理,主要是JDK動態代理和CGLib動態代理
第一:JDK動態代理
概念:利用反射機制生成一個實現代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理
條件:接口+實現類
缺陷:不能代理實現類,無接口
第二:CGLib(code generize library)
概念:利用asm開源包,對代理對象類的class文件加載進來,通過修改其字節碼生成子類來處理,相當於繼承,然後對方法進行增強處理,所以被代理類不能被final修飾
條件:實現類
缺陷:必須依賴於CGLib的類庫
實現步驟:
- 創建一個實現接口InvocationHandler的類,它必須實現invoke方法
- 創建被代理的類以及接口
- 通過Proxy的靜態方法 newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)創建一個代理
- 通過代理調用方法
jdk代理實現
第一步:創建接口和實現類
public interface ItemsService {
//測試jdk代理,cglib不需要接口
void jdkProxy();
}
public class ItemsServiceImpl implements ItemsService {
public void jdkProxy() {
System.out.println("jdk測試代理方式被執行");
}
public void cglibProxy() {
System.out.println("cglb測試代理方式被執行");
}
}
第二步:創建切面增強類
public class MyAspect {
public void before(){
System.out.println("before");
}
public void after(){
System.out.println("after");
}
}
第三步:創建動態代理工具類
public class JDKProxyFactory {
//增強的類
final static MyAspect myAspect=new MyAspect();
//代理創建實例,參數o代表創建的一個空對象
public static Object createInstance(final Object o){
//參數一:類加載器,參數二:接口名,參數三:自定義增強類,採取匿名自定義
Object object= Proxy.newProxyInstance(o.getClass().getClassLoader(), o.getClass().getInterfaces(), new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//加入增強的方法
myAspect.before();
//執行原來的方法
Object o1=method.invoke(o,args);
myAspect.after();
return o1;
}
});
//返回代理對象
return object;
}
}
第四步:測試
public class ProxyTest {
@Test
public void test1(){
//創建一個空對象
ItemsService itemsService=new ItemsServiceImpl();
//創建代理對象實例
ItemsService itemsService1= (ItemsService) JDKProxyFactory.createInstance(itemsService);
try {
//測試方法
itemsService1.jdkProxy();
} catch (Exception e) {
e.printStackTrace();
}
}
“
cglib代理實現
第一步:創建實現類,不能被final修飾,見jdk代理實現類
第二步:創建增強類,見jdk代理實現
第三步:編寫代理類
因爲cglib是對指定的類先創建其子類,然後實現其所有方法,所以這裏這是對itemsSrviceImpl類進行代理
public class CglibProxyFactory {
//增強的類
final static MyAspect myAspect=new MyAspect();
public static ItemsServiceImpl createProxy(Object o){
//創建類的子類
final ItemsServiceImpl itemsService=new ItemsServiceImpl();
//創建核心類
Enhancer enhancer=new Enhancer();
//設置父類
enhancer.setSuperclass(itemsService.getClass());
//代理類實現回調方法,類似jdk代理的增強器
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//設置增強方法
myAspect.before();
Object obj=method.invoke(itemsService,args);
//methodProxy.invokeSuper(proxy,args);
//設置增強方法
myAspect.after();
return obj;
}
});
return (ItemsServiceImpl) enhancer.create();
}
}
第四步:測試
@Test
public void test2(){
ItemsServiceImpl itemsService1= CglibProxyFactory.createProxy(new ItemsServiceImpl());
try {
//測試方法
itemsService1.cglibProxy();
} catch (Exception e) {
e.printStackTrace();
}
}
結果爲:
總結:
jdk代理源碼見:http://blog.csdn.net/jiankunking/article/details/52143504