标签:
1,成员变量
?代理类的构造函数参数。默认每个代理类都具有一个invocationHandler的构造方法。(本文代码主要基于jdk 1.7)
/** parameter types of a proxy class constructor */private static final Class<?>[] constructorParams ={ InvocationHandler.class };
?缓存代理对象。
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
代理对象的InvacationHandler,每个代理对象都有一个与之对应的Invocationhandler对象。
/*** the invocation handler for this proxy instance.* @serial*/protected InvocationHandler h;
2,构造方法
?私有构造方法,禁止外部直接通过new关键字生成代理对象。
/*** Prohibits instantiation.*/private Proxy() {}
/*** Constructs a new {@code Proxy} instance from a subclass* (typically, a dynamic proxy class) with the specified value* for its invocation handler.** @param h the invocation handler for this proxy instance*/protected Proxy(InvocationHandler h) {doNewInstanceCheck();this.h = h;}
3,newProxyInstance方法
?newProxyInstance方法是我们外部生成代理对象时候主要调用的方法。
@CallerSensitivepublic static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException{if (h == null) {//检查InvocationHandler,如果为空,直接抛出异常throw new NullPointerException();}final Class<?>[] intfs = interfaces.clone();final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
//检查对应的classLoader是否为空,以及接口是否可见checkProxyAccess(Reflection.getCallerClass(), loader, intfs);}/** Look up or generate the designated proxy class.*/Class<?> cl = getProxyClass0(loader, intfs);/** Invoke its constructor with the designated invocation handler.*/try {final Constructor<?> cons = cl.getConstructor(constructorParams);final InvocationHandler ih = h;if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {// create proxy instance with doPrivilege as the proxy class may// implement non-public interfaces that requires a special permissionreturn AccessController.doPrivileged(new PrivilegedAction<Object>() {public Object run() {return newInstance(cons, ih);}});} else {return newInstance(cons, ih);}} catch (NoSuchMethodException e) {throw new InternalError(e.toString());}}
private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces) {if (interfaces.length > 65535) {throw new IllegalArgumentException("interface limit exceeded");}// If the proxy class defined by the given loader implementing// the given interfaces exists, this will simply return the cached copy;// otherwise, it will create the proxy class via the ProxyClassFactoryreturn proxyClassCache.get(loader, interfaces);}
public V get(K key, P parameter) {Objects.requireNonNull(parameter);//校验接口不为空expungeStaleEntries();Object cacheKey = CacheKey.valueOf(key, refQueue);//生成缓存对象
// lazily install the 2nd level valuesMap for the particular cacheKey
//内部缓存map中获取对应的对象ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);if (valuesMap == null) {//为空ConcurrentMap<Object, Supplier<V>> oldValuesMap= map.putIfAbsent(cacheKey,valuesMap = new ConcurrentHashMap<>());//map中存入对应cacheKey和Mapif (oldValuesMap != null) {valuesMap = oldValuesMap;}}// create subKey and retrieve the possible Supplier<V> stored by that// subKey from valuesMapObject subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));Supplier<V> supplier = valuesMap.get(subKey);Factory factory = null;while (true) {if (supplier != null) {// supplier might be a Factory or a CacheValue<V> instanceV value = supplier.get();//Supplier实现了一个get接口。主要由Factory实现其具体接口。if (value != null) {return value;//存在,则直接返回}}// else no supplier in cache// or a supplier that returned null (could be a cleared CacheValue// or a Factory that wasn‘t successful in installing the CacheValue)// lazily construct a Factoryif (factory == null) {factory = new Factory(key, parameter, subKey, valuesMap);//创建Factory}if (supplier == null) {//Suppliersupplier = valuesMap.putIfAbsent(subKey, factory);if (supplier == null) {// successfully installed Factorysupplier = factory;}// else retry with winning supplier} else {if (valuesMap.replace(subKey, supplier, factory)) {// successfully replaced// cleared CacheEntry / unsuccessful Factory// with our Factorysupplier = factory;} else {// retry with current suppliersupplier = valuesMap.get(subKey);}}}}
此处主要用到了ConcurrentHashMap的相关操作。
我们主要的操作都是通过自定义的Factory的get方法来获取我们对应的缓存对象。
private final class Factory implements Supplier<V> {private final K key;private final P parameter;private final Object subKey;private final ConcurrentMap<Object, Supplier<V>> valuesMap;Factory(K key, P parameter, Object subKey,ConcurrentMap<Object, Supplier<V>> valuesMap) {this.key = key;this.parameter = parameter;this.subKey = subKey;this.valuesMap = valuesMap;}@Overridepublic synchronized V get() { // serialize access// re-checkSupplier<V> supplier = valuesMap.get(subKey);if (supplier != this) {// something changed while we were waiting:// might be that we were replaced by a CacheValue// or were removed because of failure ->// return null to signal WeakCache.get() to retry// the loopreturn null;}// else still us (supplier == this)// create new valueV value = null;try {value = Objects.requireNonNull(valueFactory.apply(key, parameter));} finally {if (value == null) { // remove us on failurevaluesMap.remove(subKey, this);}}// the only path to reach here is with non-null valueassert value != null;// wrap value with CacheValue (WeakReference)CacheValue<V> cacheValue = new CacheValue<>(value);// try replacing us with CacheValue (this should always succeed)if (valuesMap.replace(subKey, this, cacheValue)) {// put also in reverseMapreverseMap.put(cacheValue, Boolean.TRUE);} else {throw new AssertionError("Should not reach here");}// successfully replaced us with new CacheValue -> return the value// wrapped by itreturn value;}}
在此处,通过valueFactory的apply方法来生成一个新的代理对象,然后放入缓存。valueFactory为BiFunction接口实例,主要实现有KeyFactory和ProxyClassFactory。ProxyClassFactory是生成代理对象的关键。
/*** A factory function that generates, defines and returns the proxy class given* the ClassLoader and array of interfaces.*/private static final class ProxyClassFactoryimplements BiFunction<ClassLoader, Class<?>[], Class<?>>{// prefix for all proxy class namesprivate static final String proxyClassNamePrefix = "$Proxy";//代理名称前缀// next number to use for generation of unique proxy class namesprivate static final AtomicLong nextUniqueNumber = new AtomicLong();//代理名称的下一个名字@Overridepublic Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {//循环检查接口
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);for (Class<?> intf : interfaces) {/** Verify that the class loader resolves the name of this* interface to the same Class object.*/Class<?> interfaceClass = null;try {interfaceClass = Class.forName(intf.getName(), false, loader);} catch (ClassNotFoundException e) {}if (interfaceClass != intf) {throw new IllegalArgumentException(intf + " is not visible from class loader");}/** Verify that the Class object actually represents an* interface.*/if (!interfaceClass.isInterface()) {throw 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());}}String proxyPkg = null; // package to define proxy class in/** Record the package of a non-public proxy interface so that the* proxy class will be defined in the same package. Verify that* all non-public proxy interfaces are in the same package.*/for (Class<?> intf : interfaces) {int flags = intf.getModifiers();if (!Modifier.isPublic(flags)) {String name = intf.getName();int n = name.lastIndexOf(‘.‘);String pkg = ((n == -1) ? "" : name.substring(0, n + 1));if (proxyPkg == null) {proxyPkg = pkg;} else if (!pkg.equals(proxyPkg)) {throw new IllegalArgumentException("non-public interfaces from different packages");}}}if (proxyPkg == null) {// if no non-public proxy interfaces, use com.sun.proxy packageproxyPkg = ReflectUtil.PROXY_PACKAGE + ".";}/** Choose a name for the proxy class to generate.*/long num = nextUniqueNumber.getAndIncrement();String proxyName = proxyPkg + proxyClassNamePrefix + num;/** Generate the specified proxy class.*/byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);//生成最终的代理对象try {return defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);} 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());}}}
最终的代理对象由ProxyGenerator.generateProxyClass实现。改类的源码SUN并未提供,只能尝试一些反编译技术查看,在此省略。
以上即为JDK实现动态代理的基本原理。我们抛开各种技术细节总结,可以整体的将实现过程概括为下面:
?1)检查内部缓存代码是否存在对应ClassLoader对应的代理对象。存在则直接返回,否则生成。
?2)生成代理对象时,获取对应的Factory视力,如果存在Factory实例,则直接调用其get方法,否则生成Factory实例。
?3)调用Factory的get方法,再调用ProxyClassFactory的apply方法,apply方法调用ProxyGenerator.generateProxyClass方法生成最终的代理对象。在Fatory内部,生成代理对象后,缓存代理对象。
看了如上JDK Proxy类的实现,整体结构我们可以有个较为清晰的认识。但是对具体生成代理对象,以为SUN隐藏了内部实现,我们可能较为模糊,下面我们可以自己使用反射来完成一个自己的Proxy类。
个人认为,Proxy内的内部,只是将我们的接口,以及InvocationHandler方法进行组装而已。
?此部分代码参考博客:http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/
?
package com.jing.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;/*** 自定义代理,实现对实例进行代理** @author jinglongjun** @param <T>*/public final class MyProxy {private InvocationHandler handler;// 处理器/*** 禁止外部访问*/private MyProxy() {}public MyProxy(InvocationHandler handler) {this.handler = handler;}/*** 代理执行方法** @param methodName* 代理方法名称* @param obj* 目标对象* @param args* 方法执行参数* @param parameterTypes* 方法参数类型数组* @return 方法执行返回值* @throws Exception*/public Object invoke(String methodName, Object obj,Class<?>[] parameterTypes, Object... args) throws Exception {if (obj == null)throw new NullPointerException("目标对象不能为空!");// 1,获取代理对象方法Method method = obj.getClass().getMethod(methodName, parameterTypes);// 获取方法// 2.获取InvocationHandler的invke方法,并执行。此处传入了目标对象的Method对象Object result = null;try {//执行Handler的Invoke方法result = handler.invoke(this, method, args);} catch (Throwable e) {e.printStackTrace();}return result;}}
调用实例
package com.jing.proxy;public class TestMyProxy {public static void main(String[] args) throws Exception {HelloSubject helloSubject = new HelloSubject();SubHandler subHandler = new SubHandler(helloSubject);MyProxy proxy = new MyProxy(subHandler);Object result = proxy.invoke("doSomething", helloSubject, null, new Object[]{});System.out.println(result);}}
如上,即为整体JDK动态代理的实现,部分代码我写的比较模糊,比如缓存的具体实现步骤,此处可以在后续有时间再深入地学习,毕竟不能一口吃成胖子,还是要循环渐进。
我们通过对源码的分析很容易帮助我们更好的理解动态代理模式。
了解了动态代理的实现原理,后续我们可以分析开源框架中对动态代理模式的应用。
具体后续会根据Spring AOP的代码实现来查看动态代理对框架的作用。
?
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/mergades/article/details/47069371