1.靜態(tài)代理,動(dòng)態(tài)代理
靜態(tài)代理:代理類和代理目標(biāo)存在硬編碼關(guān)系礁鲁,耦合度高
動(dòng)態(tài)代理:代理類通過(guò)java反射照捡,在jvm運(yùn)行時(shí)動(dòng)態(tài)生成涧偷,實(shí)現(xiàn)代碼解耦
2.JDK動(dòng)態(tài)代理莽鸭,cglib動(dòng)態(tài)代理
JDK動(dòng)態(tài)代理:通過(guò)反射類Proxy以及InvocationHandler回調(diào)接口實(shí)現(xiàn)的劣摇,被代理類必須實(shí)現(xiàn)自接口
cglib動(dòng)態(tài)代理:通過(guò)ASM(字節(jié)碼技術(shù))框架生成代理類荤懂,被代理對(duì)象為public且不為final修飾茁裙,因?yàn)閏glib原理是動(dòng)態(tài)生成被代理類的子類
接口(Subject):
interface HelloService {
void sayHello();
}
委托類:
class HelloServiceImpl implements HelloService {
@Override
public void sayHello() {
System.out.println("Hello World!");
}
}
JDK代理核心代碼,構(gòu)造代理對(duì)象
class HelloServiceDynamicProxy {
private HelloService helloService;
public HelloServiceDynamicProxy(HelloService helloService) {
this.helloService = helloService;
}
public Object getProxyInstance() {
return Proxy.newProxyInstance(helloService.getClass().getClassLoader(), helloService.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before say hello...");
Object ret = method.invoke(helloService, args);
System.out.println("After say hello...");
return ret;
}
});
}
}
}
測(cè)試類:
public class HelloServieDynamicProxyTest {
public static void main(String[] args){
HelloService helloService = new HelloServiceImpl();
HelloService dynamicProxy = (HelloService) new HelloServiceDynamicProxy(helloService).getProxyInstance();
dynamicProxy.sayHello();
}
}
輸出結(jié)果:
Before say hello...
Hello World!
After say hello...
了解過(guò)動(dòng)態(tài)代理實(shí)現(xiàn)后节仿,我們知道不管何種代理晤锥,作用對(duì)象是類,通過(guò)生成代理類廊宪,調(diào)用其方法查近。
結(jié)論:
Spring AOP 則是基于動(dòng)態(tài)代理底層實(shí)現(xiàn),對(duì)目標(biāo)類的方法調(diào)用植入增強(qiáng)功能代碼
所以基于aop的注解(例:@Transactional)具有共性特征自調(diào)用失效
(調(diào)用類中第一個(gè)方法沒(méi)有注解挤忙,那么該方法這種調(diào)用本類中的其他注解方法都不起作用)
粗暴的解決方法
// 在A方法內(nèi)部調(diào)用B方法
// 1.直接調(diào)用B霜威,注解失效。
// 2.拿到代理類對(duì)象册烈,再調(diào)用B(X類的B方法)戈泼。
((X)AopContext.currentProxy()).B()