Jdk 動(dòng)態(tài)代理
Jdk動(dòng)態(tài)代理,利用反射,實(shí)現(xiàn) InvocationHandler 接口。Jdk 動(dòng)態(tài)代理需要實(shí)現(xiàn)類(lèi)通過(guò)接口定義業(yè)務(wù)方法,也就是說(shuō),委托類(lèi)必須實(shí)現(xiàn)一個(gè)定義了業(yè)務(wù)方法的接口,在接口里約定需要代理的方法,并且只能對(duì)接口里約定的方法實(shí)現(xiàn)代理。由于需要委托類(lèi)實(shí)現(xiàn)一個(gè)接口,這是一個(gè)局限性。
- Subject 類(lèi)
public interface Subject {
void doSomething();
}
- RealSubject 類(lèi)
public class RealSubject implements Subject {
@Override
public void doSomething() {
System.out.println("do something");
}
}
- Jdk 代理
public class JdkProxy implements InvocationHandler {
private Object target;
public JdkProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
System.out.println("jdk proxy before");
result = method.invoke(target, args);
System.out.println("jdk proxy after");
return result;
}
}
- Jdk 代理測(cè)試
public class JdkProxyTest {
@Test
public void testJdkProxy() {
RealSubject realSubject = new RealSubject();
Subject subject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), new JdkProxy(realSubject));
subject.doSomething();
}
}
運(yùn)行結(jié)果:
jdk proxy before
do something
jdk proxy after
Cglib 動(dòng)態(tài)代理
Cglib 代理是針對(duì)類(lèi)來(lái)實(shí)現(xiàn)代理的,并不要求委托類(lèi)必須實(shí)現(xiàn)接口,它的原理是對(duì)指定的目標(biāo)類(lèi)生成一個(gè)子類(lèi),并覆蓋其中方法實(shí)現(xiàn)增強(qiáng),采用的是繼承的方式。由于是采用繼承的方式,所以用 Cglib 實(shí)現(xiàn)的代理類(lèi)是不能處理被final關(guān)鍵字修飾的方法的。
- Cglib 代理
public class CglibProxy implements MethodInterceptor {
public Object getInstance(Class clazz) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object result;
System.out.println("cglib proxy before");
result = methodProxy.invokeSuper(o, objects);
System.out.println("cglib proxy after");
return result;
}
}
在上文中可以看到,代理對(duì)象的生成過(guò)程是由 Enhancer 類(lèi)來(lái)實(shí)現(xiàn)的,大概步驟是:
- 生成代理類(lèi) Class 的二進(jìn)制字節(jié)碼;
- 通過(guò) Class.forName 加載二進(jìn)制字節(jié)碼,生成Class對(duì)象;
- 通過(guò)反射機(jī)制獲取實(shí)例構(gòu)造,并初始化代理類(lèi)對(duì)象。
intercept() 方法攔截目標(biāo)類(lèi)方法的調(diào)用,o 表示目標(biāo)類(lèi)的實(shí)例,method 為目標(biāo)類(lèi)方法的反射對(duì)象,objects 為方法的動(dòng)態(tài)入?yún)?,methodProxy 為代理類(lèi)實(shí)例。
- Cglib 代理測(cè)試
public class CglibProxyTest {
@Test
public void testCglibProxy() {
RealSubject realSubject = (RealSubject) new CglibProxy().getInstance(RealSubject.class);
realSubject.doSomething();
}
}
運(yùn)行結(jié)果:
cglib proxy before
do something
cglib proxy after