动态代理
主要是实现动态增强接口的功能
具体实现:
- 写一个接口,接口中封装了客户端需要的操作。
- 写一个委托类实现该接口
- 写一个代理类实现
InvocationHandler
接口,这个类中存在委托类的引用- 客户端利用
Proxy
类的静态方法(反射技术),让接口关联代理实现类的对象,利用接口来调用方法,实际通过代理来访问委托类的方法。
静态代理
写一个接口A,定义一些功能
写一个类B,实现接口
写一个类C,实现接口,并且C的内部有一个B实例,构造方法中也需要传入一个B对象b,重写接口方法时实际上是调用b对象的对应方法,但是此时可以添加一些其他的操作,相当于加强了类。
图示
代码
// 静态代理,定义了一个代理类并且内部包含接口的一个实现类,代理类再实现接口, // 并且通过内部的类实例调用方法,本身只用于加强方法 public class SimpleStaticProxyDemo { static interface IService { public void sayHello(); } static class RealService implements IService { @Override public void sayHello() { System.out.println("你好呀!!"); } } static class TraceProxy implements IService { private IService realService; public TraceProxy(IService realService) { this.realService = realService; } @Override public void sayHello() { System.out.println("进入sayHello方法"); realService.sayHello(); System.out.println("退出sayHello方法"); } } public static void main(String[] args) { IService realService = new RealService(); IService proxyService = new TraceProxy(realService); proxyService.sayHello(); } }
动态代理
JDK动态代理
代码
import java.lang.reflect.*; public class SimpleJDKDynamicProxyDemo { static interface IService { public void sayHello(); } static class RealService implements IService { @Override public void sayHello() { System.out.println("你好呀!!"); } } static class SimpleInvocationHandler implements InvocationHandler { private Object realObject; public SimpleInvocationHandler(Object realObject) { this.realObject = realObject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("进入" + method.getName() + "方法"); // 调用realObject对象的method方法,参数是args Object result = method.invoke(realObject, args); System.out.println("离开" + method.getName() + "方法"); return result; } } public static void main(String[] args) throws Exception { IService realService = new RealService(); // 通过Proxy.getProxyClass创建代理类定义,类定义会被缓存 Class proxyClass = Proxy.getProxyClass(IService.class.getClassLoader(), new Class<?>[]{IService.class}); // 获取代理类的构造方法,构造方法中会有一个InvocationHandler类型的参数 Constructor constructor = proxyClass.getConstructor(new Class[]{InvocationHandler.class}); // 创建InvocationHandler和IService对象 InvocationHandler handler = new SimpleInvocationHandler(realService); IService proxyService = (IService) constructor.newInstance(handler); proxyService.sayHello(); } }
本质上来看Proxy.getProxyClass会动态生成一个代理类,
h
是一个InvocationHandler类实例final class $Proxy0 extends Proxy implements SimpleJDKDynamicProxyDemo.IService { private static Method m1; private static Method m3; private static Method m2; private static Method m0; public $Proxy0(InvocationHandler paramInvocationHandler) { super(paramInvocationHandler); } public final boolean equals(Object paramObject) { return ((Boolean) h.invoke(this, m1, new Object[]{paramObject})).booleanValue(); } public final void sayHello() { h.invoke(this, m3, null); } public final String toString() { return (String) h.invoke(this, m2, null); } public final int hashCode() { return ((Integer) h.invoke(this, m0, null)).intValue(); } static { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")}); m3 = Class.forName("edu.hut.proxy.SimpleJDKDynamicProxyDemo$IService").getMethod("sayHello", new Class[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); } }
作用
可以实现一种方法模板,只需要传入接口的class和一个实现了接口的类对象,就可以增强对应的方法(比如打印日志)
代码
import java.lang.reflect.*; public class GeneralProxyDemo { static interface IServiceA { public void sayHello(); } static class ServiceAImpl implements IServiceA { @Override public void sayHello() { System.out.println("你好呀!!"); } } static interface IServiceB { public void fly(); } static class ServiceBImpl implements IServiceB { @Override public void fly() { System.out.println("正在飞翔!!"); } } static class SimpleInvocationHandler implements InvocationHandler { private Object realObj; public SimpleInvocationHandler(Object realObj) { this.realObj = realObj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("进入 " + realObj.getClass().getSimpleName() + "类的" + method.getName() + "方法"); Object result = method.invoke(realObj, args); System.out.println("退出 " + realObj.getClass().getSimpleName() + "类的" + method.getName() + "方法"); return result; } } private static <T> T getProxy(Class<T> intf, T realObj) { return (T) Proxy.newProxyInstance(intf.getClassLoader(), new Class<?>[] { intf }, new SimpleInvocationHandler(realObj)); } public static void main(String[] args) throws Exception { IServiceA a = new ServiceAImpl(); IServiceA aProxy = getProxy(IServiceA.class, a); aProxy.sayHello(); System.out.println("\n--------------分界线--------------\n"); IServiceB b = new ServiceBImpl(); IServiceB bProxy = getProxy(IServiceB.class, b); bProxy.fly(); } } // 运行结果 进入 ServiceAImpl类的sayHello方法 你好呀!! 退出 ServiceAImpl类的sayHello方法 --------------分界线-------------- 进入 ServiceBImpl类的fly方法 正在飞翔!! 退出 ServiceBImpl类的fly方法
cglib动态代理
作用:可以代理类(JDK代理无法实现)
代码
public class SimpleCGLibDemo { static class RealService { public void sayHello() { System.out.println("hello"); } } static class SimpleInterceptor implements MethodInterceptor { @Override public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("entering " + method.getName()); Object result = proxy.invokeSuper(object, args); System.out.println("leaving " + method.getName()); return result; } } @SuppressWarnings("unchecked") private static <T> T getProxy(Class<T> cls) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(cls); enhancer.setCallback(new SimpleInterceptor()); return (T) enhancer.create(); } public static void main(String[] args) throws Exception { RealService proxyService = getProxy(RealService.class); proxyService.sayHello(); } }