您的位置:首页 > 其它

动态代理模式2--源码分析

2015-07-26 16:53 441 查看

Proxy源码

1,成员变量

​代理类的构造函数参数。默认每个代理类都具有一个invocationHandler的构造方法。(本文代码主要基于jdk 1.7)

/** parameter types of a proxy class constructor*/

private static final Class<?>[] constructorParams =

{ InvocationHandler.class };

[/code]

​缓存代理对象。

private static final WeakCache<ClassLoader, Class<?>[], Class<?>>

proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

[/code]

代理对象的InvacationHandler,每个代理对象都有一个与之对应的Invocationhandler对象。

/**

* the invocation handler for this proxy instance.

* @serial

*/

protected InvocationHandler h;

[/code]

2,构造方法

​私有构造方法,禁止外部直接通过new关键字生成代理对象。

/**

* Prohibits instantiation.

*/

private Proxy() {

}

[/code]

protected构造函数。

/**

* 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;

}

[/code]

3,newProxyInstance方法

​newProxyInstance方法是我们外部生成代理对象时候主要调用的方法。

@CallerSensitive

public 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 permission

return 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());

}

}

[/code]

我们可以看到,最主要的方法在getProxyClass0方法,我们查看其对应的方法。

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 ProxyClassFactory

return proxyClassCache.get(loader, interfaces);

}

[/code]

我们从代码注释中可以看到,此出主要出缓存中获取代理对象。缓存表中主要存放以类加载器为key的Map对象。我们查看缓存的proxyClassCache的get方法。

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和Map

if (oldValuesMap != null) {

valuesMap = oldValuesMap;

}

}


// create subKey and retrieve the possible Supplier<V> stored by that

// subKey from valuesMap

Object 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> instance

V 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 Factory

if (factory == null) {

factory = new Factory(key, parameter, subKey, valuesMap);//创建Factory

}


if (supplier == null) {//Supplier

supplier = valuesMap.putIfAbsent(subKey, factory);

if (supplier == null) {

// successfully installed Factory

supplier = factory;

}

// else retry with winning supplier

} else {

if (valuesMap.replace(subKey, supplier, factory)) {

// successfully replaced

// cleared CacheEntry / unsuccessful Factory

// with our Factory

supplier = factory;

} else {

// retry with current supplier

supplier = valuesMap.get(subKey);

}

}

}

}

[/code]

此处主要用到了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;

}


@Override

public synchronized V get() { // serialize access

// re-check

    Supplier<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 loop

return null;

}

// else still us (supplier == this)


// create new value

V value = null;

    try {

value = Objects.requireNonNull(valueFactory.apply(key, parameter));

} finally {

if (value == null) { // remove us on failure

valuesMap.remove(subKey, this);

}

}

// the only path to reach here is with non-null value

assert 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 reverseMap

reverseMap.put(cacheValue, Boolean.TRUE);

} else {

throw new AssertionError("Should not reach here");

}


// successfully replaced us with new CacheValue -> return the value

// wrapped by it

return value;

}

}

[/code]

在此处,通过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 ProxyClassFactory

implements BiFunction<ClassLoader, Class<?>[], Class<?>>

{

// prefix for all proxy class names

private static final String proxyClassNamePrefix = "$Proxy";//代理名称前缀


// next number to use for generation of unique proxy class names

private static final AtomicLong nextUniqueNumber = new AtomicLong();//代理名称的下一个名字


@Override

public 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 package

proxyPkg = 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());

}

}

}

[/code]

最终的代理对象由ProxyGenerator.generateProxyClass实现。改类的源码SUN并未提供,只能尝试一些反编译技术查看,在此省略。

以上即为JDK实现动态代理的基本原理。我们抛开各种技术细节总结,可以整体的将实现过程概括为下面:

​1)检查内部缓存代码是否存在对应ClassLoader对应的代理对象。存在则直接返回,否则生成。

​2)生成代理对象时,获取对应的Factory视力,如果存在Factory实例,则直接调用其get方法,否则生成Factory实例。

​3)调用Factory的get方法,再调用ProxyClassFactory的apply方法,apply方法调用ProxyGenerator.generateProxyClass方法生成最终的代理对象。在Fatory内部,生成代理对象后,缓存代理对象。

实现自己的Proxy类

看了如上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;

}

}

[/code]

调用实例

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);

}

}

[/code]

如上,即为整体JDK动态代理的实现,部分代码我写的比较模糊,比如缓存的具体实现步骤,此处可以在后续有时间再深入地学习,毕竟不能一口吃成胖子,还是要循环渐进。

我们通过对源码的分析很容易帮助我们更好的理解动态代理模式。
了解了动态代理的实现原理,后续我们可以分析开源框架中对动态代理模式的应用。
具体后续会根据Spring AOP的代码实现来查看动态代理对框架的作用。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: