您的位置:首页 > 编程语言 > Java开发

Java动态代理实现原理浅析

2016-05-06 09:55 429 查看

代码编写

接口编写

public interface TargetInterface {

void targetMethod();

}


实现类编写

public class Target implements TargetInterface {

@Override

public void targetMethod() {

System.out.println("target method invoking ...");

}

}


增强类编写

public class ProxyHandler implements InvocationHandler {

private Object proxyTarget;

public ProxyHandler(Object proxyTarget) {

this.proxyTarget = proxyTarget;

}

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println("do somethings before target method invoke");

Object result = method.invoke(proxyTarget, args);

System.out.println("do somethings after target method invoke");

return result;

}

}


测试类编写

public class ProxyTest {

public static void main(String[] args) {

System.out.println(Thread.currentThread().getContextClassLoader());

TargetInterface target = new Target();

ClassLoader loader = target.getClass().getClassLoader();

Class<?>[] interfaces = target.getClass().getInterfaces();

InvocationHandler proxyHandler = new ProxyHandler(target);

TargetInterface proxyTarget = (TargetInterface) Proxy.newProxyInstance(loader, interfaces, proxyHandler);

proxyTarget.targetMethod();

}

}


源码分析(源码篇幅过多,省略部分由“…”表示)

代码中proxyTarget增强类是由Proxy.newProxyInstance(…)生成的,查看该方法源码:

``public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException{

...

// step1:从缓存中查找代理类,若未缓存则生成后缓存,否则直接从缓存中获取.

Class<?> cl = getProxyClass0(loader, intfs);

try {

...

//step2:反射生成代理类实例

return newInstance(cons, ih);

...

} catch (NoSuchMethodException e) {

...

}

}


代码中可以看出,代理类的生成主要分为两步:

- 生成代理类

- 反射生成代理类实例

step1:

Proxy.getProxyClass0

private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces) {

...

// Proxy类中维护了一个WeakCache对象,用于缓存动态生成的类,WeakCache.get方法不仅执行查找操作,当对象不存在时也会执行生成操作,下面来看下该方法的源码

return proxyClassCache.get(loader, interfaces);

}


WeakCache.get

public V get(K key, P parameter) {

...

while (true) {

if (supplier != null) {

//已从缓存中查找到对象,直接返回

V value = supplier.get();

if (value != null) {

return value;

}

}

if (factory == null) {

//已从缓存中查找到对象,且调用该对象的get方法生成代理类后直接返回,get方法实现下文详述

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

}

if (supplier == null) {

//将新生成的对象缓存

supplier = valuesMap.putIfAbsent(subKey, factory);

if (supplier == null) {

supplier = factory;

}

} else {

...

}

}

}

}


此方法会不断的循环以及重复判断,均是在考虑线程安全问题。此处未做深究。

Faotory.get

public synchronized V get() {

...

try {

//实现生成代理类对象,此方法在内部类ProxyClassFactory中实现

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

} finally {

...

}

...

return value;

}


ProxyClassFactory.apply

public Class apply(ClassLoader loader, Class[] interfaces) {

//校验interfaces

...

String proxyPkg = null;

...

//生成packagename,默认为com.sun.proxy

if (proxyPkg == null) {

// if no non-public proxy interfaces, use  package

proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";

}

//生成classname,采用AutomicLong自增方式

long num = nextUniqueNumber.getAndIncrement();

String proxyName = proxyPkg + proxyClassNamePrefix + num;

// 生成字节码文件

byte[] proxyClassFile = ProxyGenerator.generateProxyClass(

proxyName, interfaces);

// 调用native方法,加载生成的字节码文件,并返回代理类的引用

try {

return defineClass0(loader, proxyName,

946c
proxyClassFile, 0, proxyClassFile.length);

} catch (ClassFormatError e) {

...

}

}


将生成的proxyClassFile字节码写入到文件并反编译后,信息如下:

package com.sun.proxy.$Proxy;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

import java.lang.reflect.UndeclaredThrowableException;

import x.constant.proxy.TargetInterface;

public final class 1 extends Proxy implements TargetInterface {

private static Method m3;

private static Method m1;

private static Method m0;

private static Method m2;

public 1(InvocationHandler paramInvocationHandler) throws  {

super(paramInvocationHandler);

}

public final void targetMethod() throws {

try {

this.h.invoke(this, m3, null);

return;

}catch (Error|RuntimeException localError) {

throw localError;

}catch (Throwable localThrowable){

throw new UndeclaredThrowableException(localThrowable);

}

}

public final boolean equals(Object paramObject) {

...

}

public final int hashCode() {

...

}

public final String toString() throws {

...

}

static {

try {

m3 = Class.forName("x.constant.proxy.TargetInterface").getMethod("targetMethod", new Class[0]);

m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });

m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);

m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);

return;

}catch (NoSuchMethodException localNoSuchMethodException){

throw new NoSuchMethodError(localNoSuchMethodException.getMessage());

}

catch (ClassNotFoundException localClassNotFoundException)

{

throw new NoClassDefFoundError(localClassNotFoundException.getMessage());

}

}

}


可以看到,该类位于com.sun.proxy.$Proxy包下,继承Proxy对象且实现我们自定义的TargetInterface接口;构造方法需要一个InvocationHandler对象做为参数;增强后的targetMethod方法会调用InvocationHandler对象的invoke方法。

step2

增强后的类信息已经加载到JVM中并得到了该类的引用,通过反射机制调用该类的构造方法并传入我们自定义的InvocationHandler对象做为参数,即可生成该代理类对象,此处不再做解析。

通过源代码的阅读可以发现,java动态代理的实现过程:

1. 根据Interface动态生成一个该接口的代理类,并通过调用InvocationHandler中的invoke方法的方式来实现Interface中定义的方法

2. 动态加载该代理类,并通过反射的方式获取该代理类的对象。

归根结底,其实现也是通过字节码生成ASM技术来实现的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: