因为现在在在学java的一些框架技术,比如ssh,mybatis等,总是提到动态代理,而且用到的还蛮多的,因此将jdk动态代理好好研究一下。
代理模式
代理模式是java中一种常见的设计模式,他的特征是代理类和委托类实现相同的接口。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。java动态代理的出现,使我们不需要手动写代理类,只需要提供一组接口和委托类对象,即可动态生成代理类。
CGLIB动态代理
CGLIB代理是针对类实现代理,主要是指定的类生成一个子类,覆盖其中的所有方法,所有该类或方法不能声明称final的。
JDK动态代理
代理对象和目标对象实现了相同的接口,目标对象作为代理代理对象的一个属性,可以在调用目标对象响应方法前后加上其他业务的逻辑。JDK动态代理只能针对实现了接口的类生成代理。
CGLIB测试代码:
定义一个实现MethodInterceptor的方法:
package com.jcw.proxy; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class DynamicProxyByCGLib implements MethodInterceptor {
private Object target; public DynamicProxyByCGLib(Object target) { this.target = target; } public Object getInstance() { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); enhancer.setCallback(this); return enhancer.create(); } public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("before intercept"); methodProxy.invokeSuper(o, objects); System.out.println("after interept"); return null; }
}
定义一个测试类:
package com.jcw.proxy;
public class CGLIBProxyTest {
public void say() {
System.out.println("say for CGLIBProxyTest");
}
public static void main(String[] args) {
CGLIBProxyTest cglibProxyTest = new CGLIBProxyTest();
DynamicProxyByCGLib dynamicProxyByCGLib = new DynamicProxyByCGLib(cglibProxyTest);
CGLIBProxyTest cglibProxyTest1 = (CGLIBProxyTest) dynamicProxyByCGLib.getInstance();
cglibProxyTest1.say();
}
}
JDK测试代码:
定义一个接口:
package com.jcw.proxy;
public interface JdkInterfaces1 {
void say();
}
定义一个实现InvocationHandler接口的类:
package com.jcw.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; public class DynamicProxyByJDK implements InvocationHandler { private Object target;
public DynamicProxyByJDK(Object target) { this.target = target; } public Object getInstance() { System.out.println("classLoader:" + target.getClass().getClassLoader()); System.out.println("interfaces:" + Arrays.toString(target.getClass().getInterfaces())); return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before invoke"); method.invoke(target, args); System.out.println("after invoke"); return null; }
}
jdk测试的类
package com.jcw.proxy; public class JdkProxyTest implements JdkInterfaces1{
public void say() { System.out.println("say for JdkProxyTest"); } public static void main(String[] args) { JdkProxyTest jdkProxyTest = new JdkProxyTest(); DynamicProxyByJDK dynamicProxyByJDK = new DynamicProxyByJDK(jdkProxyTest); JdkInterfaces1 jdkProxyTest1 = (JdkInterfaces1) dynamicProxyByJDK.getInstance(); jdkProxyTest1.say(); }
}
总结:CGLIB主要是针对类实现代理,主要通过根据指定的类生成一个代理类,覆盖其中的方法。当然对于实现接口的类,CGLIB同样可以实现。
JDK动态代理只能对实现了接口的类生成代理,而不是针对类。