Java动态代理 ----- jdk代理与cglib代理
1、jdk代理
针对接口进行代理,接口可以没有方法, InvocationHandler会拦截所有方法,不过好像意义不大....只能执行Object类的方法,执行结果有点奇怪...
package test; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class TestJdkProxy { public static void main(String[] args) { //接口的实例对象,这里用的匿名对象 Test test = new Test() { }; //拦截类 InvocationHandler invocationHandler = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //proxy为实际创建的代理类, method为代理类执行的方法, args为方法调用对应的参数 System.out.println("代理前"); Object object = method.invoke(test, args); System.out.println("代理后"); return object; } }; Test proxy = (Test) Proxy.newProxyInstance(test.getClass().getClassLoader(), test.getClass().getInterfaces(), invocationHandler); System.out.println("-------------------------------"); System.out.println(proxy.equals(proxy)); // ? 有点奇怪, 是false System.out.println("-------------------------------"); System.out.println(Integer.toHexString(proxy.hashCode())); System.out.println("-------------------------------"); System.out.println(proxy.toString()); // Object类的toString方法调用了一次hashCode方法, toString方法和hashCode方法只拦截了一次? } public interface Test { } }
输出为:
------------------------------- 代理前 代理后 false ------------------------------- 代理前 代理后 61bbe9ba ------------------------------- 代理前 代理后 test.TestJdkProxy$1@61bbe9ba
接口有方法情况:
package test; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class TestJdkProxy { public static void main(String[] args) { //接口的实例对象,这里用的匿名对象 Test test = new Test() { @Override public void test() { System.out.println("执行代理的接口方法"); } }; //拦截类 InvocationHandler invocationHandler = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //proxy为实际创建的代理类, method为代理类执行的方法, args为方法调用对应的参数 System.out.println("代理前"); Object object = method.invoke(test, args); System.out.println("代理后"); return object; } }; Test proxy = (Test) Proxy.newProxyInstance(test.getClass().getClassLoader(), test.getClass().getInterfaces(), invocationHandler); proxy.test(); } public interface Test { void test(); } }
输出为
代理前
执行代理的接口方法
代理后
2、cglib代理
代理类不能为final 类,
maven引入jar包
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </dependency>
package test; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class TestCglibProxy { public static void main(String[] args) throws Exception { MethodInterceptor handler = new MethodInterceptor() { @Override public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { //proxy为创建的代理类, 我的理解是对需要代理的类进行了继承(?), 所以需要代理的类不能为final类 System.out.println("代理前"); Object result = methodProxy.invokeSuper(proxy, objects); System.out.println("代理后"); return result; } }; Enhancer enhancer = new Enhancer(); //设置需要代理的类,不能是final类 enhancer.setSuperclass(Test.class); //设置方法拦截 enhancer.setCallback(handler); //创建代理类,根据Test构造方法所需要的参数指定create参数, 如本例中Test类有String参数构造方法 Test test = (Test) enhancer.create(new Class[]{String.class}, new Object[]{"Aa"}); test.test(); System.out.println("-------------------------------"); test = (Test) enhancer.create(); test.test(); System.out.println("-------------------------------"); //对代理类的方法都会进行拦截, Object类的toString方法调用了一次hashCode方法, toString方法和hashCode方法都进行了拦截 System.out.println(test.toString()); System.out.println("-------------------------------"); System.out.println(test.equals(test)); } public static class Test { private String str; public void test() { System.out.println("test : " + str); } public Test() { } public Test(String string) { str = string; } } }
输出为
代理前 test : Aa 代理后 ------------------------------- 代理前 test : null 代理后 ------------------------------- 代理前 代理前 代理后 代理后 test.TestCglibProxy$Test$$EnhancerByCGLIB$$d7a97ec4@7506e922 ------------------------------- 代理前 代理后 true