JDK动态代理可以在运行期间
创建一个代理类,这个代理类实现了一组给定的接口
方法。
当调用这个代理类的接口方法时,这个调用都会被定向到 InvocationHandler.invoke()方法。在这个invoke方法中,我们可以添加任何逻辑,如打印日志、安全检查等等。 之后,invoke方法会调用真实对象的方法。
动态代理是基于接口实现代理类的。因此当被代理对象没有继承接口时,JDK动态代理就无法使用,这时可以使用 CGLIB 代理,关于CGLIB 代理在下一章中介绍。
主要构成 JDK动态代理主要有 Proxy类的newProxyInstance(...)方法
和 实现InvocationHandler接口
这两个要点。
Proxy类的newProxyInstance()方法 1 2 3 4 5 6 public static Object newProxyInstance ( ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) { }
newProxyInstance()方法用于根据传入的接口类型 interfaces 返回一个动态创建的代理类的实例,方法的参数解释
第一个参数loader表示代理类的类加载器,
第二个参数interfaces表示被代理类实现的接口列表,
第三个参数h表示所指派的调用处理程序类InvocationHandler。
InvocationHandler接口的 invoke() 方法 实现InvocationHandler接口主要是重写 invoke 方法,在invoke 方法中,可以添加任何逻辑,如打印日志、安全检查等等。 如果不进行拦截的话,一定要 调用 Object invoke = method.invoke(target, args);
来执行真正的方法
简单例子
主接口类:
1 2 3 public interface IHello { public void sayHello () ; }
被代理的真实类:
1 2 3 4 5 6 7 public class Hello implements IHello { public void sayHello () { System.out.println("hello!" ); } }
JDK动态代理类必须管理一个 InvocationHandler 类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler (Object target) { this .target=target; } @Override public Object invoke (Object target, Method method, Object[] args) throws Throwable { Object invoke = method.invoke(target, args); return invoke; } }
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.lang.reflect.Proxy;public class Test { public static void main (String[] args) { IHello hello = new Hello(); InvocationHandler handler = new MyInvocationHandler(hello); IHello ihello = (IHello) Proxy.newProxyInstance(handler.getClass().getClassLoader(), hello.getClass().getInterfaces(), handler); ihello.sayHello(); } }
Proxy 源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 public class Proxy implements java .io .Serializable { public static Object newProxyInstance (ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { Objects.requireNonNull(h); final Class<?>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null ) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } Class<?> cl = getProxyClass0(loader, intfs); try { if (sm != null ) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run () { cons.setAccessible(true ); return null ; } }); } return cons.newInstance(new Object[]{h}); } catch (IllegalAccessException|InstantiationException e) { throw new InternalError(e.toString(), e); } catch (InvocationTargetException e) { Throwable t = e.getCause(); if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new InternalError(t.toString(), t); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); } } private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { if (interfaces.length > 65535 ) { throw new IllegalArgumentException("interface limit exceeded" ); } return proxyClassCache.get(loader, interfaces); } }
来源 https://blog.csdn.net/mantantan/article/details/51873755 https://www.jianshu.com/p/1a87323164f5