网站建设中要多使用图片,258网站建设,广州seo网站推广费用,广东深圳市宝安区功能概述
Java的动态代理#xff0c;是代理模式的具体实现#xff0c;即为其他对象提供一个代理以控制对某个对象的访问。Java的动态代理主要涉及两个类#xff1a;java.lang.reflect.Proxy 和 java.lang.reflect.InvocationHandler#xff0c;内部使用了缓存机制和反射机…功能概述
Java的动态代理是代理模式的具体实现即为其他对象提供一个代理以控制对某个对象的访问。Java的动态代理主要涉及两个类java.lang.reflect.Proxy 和 java.lang.reflect.InvocationHandler内部使用了缓存机制和反射机制实现。
功能实践
场景1为Map接口生成代理
用例代码
Test
public void test_jdk_dynamic_proxy_v1() {Map mapProxyInstance (Map) Proxy.newProxyInstance(ProxyTest.class.getClassLoader(), new Class[] { Map.class },new MyInvocationHandler(new HashMap()));mapProxyInstance.put(hello, world); //为接口创建代理对象后就可以直接操作接口中的方法了使用向上转型mapProxyInstance.get(hello);CharSequence csProxyInstance (CharSequence) Proxy.newProxyInstance(ProxyTest.class.getClassLoader(),new Class[] { CharSequence.class },new MyInvocationHandler(Hello World));csProxyInstance.charAt(0);csProxyInstance.length();
}// 自定义的调用处理器
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {private Object target;public MyInvocationHandler(Object target) {this.target target;}Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {Object result method.invoke(target, args);System.out.println(执行方法 method.getName() 结果值 result);return result;}
}
运行结果
执行方法put结果值null
执行方法get结果值world
执行方法charAt结果值H
执行方法length结果值11结果分析
为Map接口创建代理对象。并自定义调用处理器MyInvocationHandler在使用代理接口调用方法时就会回调MyInvocationHandler的invoke方法传入代理对象、调用的方法、参数列表等
场景2为自定义接口生成代理
用例代码
public void test_jdk_dynamic_proxy_v2() throws IOException {IHelloProxy helloProxy (IHelloProxy) Proxy.newProxyInstance(ProxyTest.class.getClassLoader(),new Class[]{IHelloProxy.class}, new MyInvocationHandler(new HelloProxyImpl())); //要指定接口的实现类在回调处理器的invoke方式时调用目标类对应方法helloProxy.setProxyName(hello);String proxyName helloProxy.getProxyName(hello);System.out.println(结果值 proxyName);
}public interface IHelloProxy {String getProxyName(String name);void setProxyName(String name);
}public class HelloProxyImpl implements IHelloProxy {private String proxyName;private static final String PREFIX proxy_;Overridepublic String getProxyName(String name) {return proxyName;}Overridepublic void setProxyName(String name) {proxyName PREFIX name;}
}注明该场景用到的MyInvocationHandler在场景1中有声明。
运行结果
执行方法setProxyName结果值null
执行方法getProxyName结果值proxy_hello
结果值proxy_hello结果分析
在创建代理对象时指定代理的接口IHelloProxy以及调用处理器MyInvocationHandler调用处理器指定了接口实现类即目标对象在调用接口方法时即调用调用代理对象的方法会回调InvocationHandler中的invoke方法可在该方法中做增强处理
原理分析
Proxy#newProxyInstance创建代理对象分析】
public class Proxy implements java.io.Serializable {private static final WeakCacheClassLoader, Class?[], Class?proxyClassCache new WeakCache(new KeyFactory(), new ProxyClassFactory()); //代码1public 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);}/** Look up or generate the designated proxy class.*/Class? cl getProxyClass0(loader, intfs); // 代码2/** Invoke its constructor with the designated invocation handler.*/try {if (sm ! null) {checkNewProxyPermission(Reflection.getCallerClass(), cl);}final Constructor? cons cl.getConstructor(constructorParams);//...代码省略...return cons.newInstance(new Object[]{h}); // 代码3} catch (IllegalAccessException|InstantiationException e) // ...代码省略...}}private static Class? getProxyClass0(ClassLoader loader,Class?... interfaces) {if (interfaces.length 65535) {throw new IllegalArgumentException(interface limit exceeded);}return proxyClassCache.get(loader, interfaces); //代码4}
}代码解析 代码1处WeakCache用来存储代理类的缓存若无缓存会通过ProxyClassFactory创建代码2处从缓存中查找代理类若没有创建代理类代码3处找到代理类包含InvocationHandler为参数的构造器Constructor通过反射机制创建代理对象代码4处从缓存中去查代理类
ProxyClassFactory#apply创建代理类分析
private static final class ProxyClassFactoryimplements BiFunctionClassLoader, Class?[], Class?
{//...代码省略...Overridepublic Class? apply(ClassLoader loader, Class?[] interfaces) {MapClass?, Boolean interfaceSet new IdentityHashMap(interfaces.length);for (Class? intf : interfaces) {Class? interfaceClass null;try {interfaceClass Class.forName(intf.getName(), false, loader); // 代码1} catch (ClassNotFoundException e) {}if (interfaceClass ! intf) {throw new IllegalArgumentException(intf is not visible from class loader);}if (!interfaceClass.isInterface()) { // 代码2throw new IllegalArgumentException(interfaceClass.getName() is not an interface);}/** Verify that this interface is not a duplicate.*/if (interfaceSet.put(interfaceClass, Boolean.TRUE) ! null) {throw new IllegalArgumentException(repeated interface: interfaceClass.getName());}}// ...代码省略.../** Generate the specified proxy class.*/byte[] proxyClassFile ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags); // 代码3try {return defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length); //代码4} catch (ClassFormatError e) {/** A ClassFormatError here means that (barring bugs in the* proxy class generation code) there was some other* invalid aspect of the arguments supplied to the proxy* class creation (such as virtual machine limitations* exceeded).*/throw new IllegalArgumentException(e.toString());}}
}代码分析 代码1处判断如是否能够通过当前加载器加载Class代码2处判断代理的是否是接口不是接口不能代理代码3处产生代理类Class的字节数组代码4处将字节数组通过native方法得到代理类的Class
功能总结
CGLIB与JDK动态代理区别 aJDK代理只能对实现接口的类生成代理CGLib是针对类实现代理bJDK代理使用的是反射机制实现aop的动态代理CGLib代理使用字节码处理框架ASMcJDK动态代理机制是委托机制CGLib则使用的继承机制