1.概述
在 《Dubbo 用戶指南 —— schema 配置參考手冊》 中,我們可以看到 <dubbo:service /> 和 <dubbo:reference /> 標籤中,可以通過 “proxy” 屬性,可以配置動態代理的生成方式:
生成動態代理方式,可選:jdk / javassist
2.整體流程
在 Consumer 中,我們調用 Service 接口的方法時,實際調用的是 Dubbo 動態代理。下面先一起來看一個生成的 proxy 代碼的示例:
package com.alibaba.dubbo.common.bytecode;
import com.alibaba.dubbo.demo.DemoService;
import com.alibaba.dubbo.rpc.service.EchoService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class proxy0
implements ClassGenerator.DC, EchoService, DemoService
{
public static Method[] methods;
private InvocationHandler handler;
public void bye(Object paramObject)
{
Object[] arrayOfObject = new Object[1];
arrayOfObject[0] = paramObject;
Object localObject = this.handler.invoke(this, methods[0], arrayOfObject);
}
public String sayHello(String paramString)
{
Object[] arrayOfObject = new Object[1];
arrayOfObject[0] = paramString;
Object localObject = this.handler.invoke(this, methods[1], arrayOfObject);
return (String)localObject;
}
public Object $echo(Object paramObject)
{
Object[] arrayOfObject = new Object[1];
arrayOfObject[0] = paramObject;
Object localObject = this.handler.invoke(this, methods[2], arrayOfObject);
return (Object)localObject;
}
public proxy0() {}
public proxy0(InvocationHandler paramInvocationHandler) {
this.handler = paramInvocationHandler;
}
}
注:生成的 proxy 類會實現我們定義的 Service 接口( 例如,此處是 DemoService )
在 Provider 中,XXXProtocol 會獲得被調用的 Exporter 對象,從而獲得到 Invoker 對象。但是呢,Invoker 對象實際和 Service 實現對象,是無法直接調用,需要有中間的一層 Wrapper 來代理分發到 Service 對應的方法。下面我們來看一個生成的 Wrapper 代碼的示例:
package com.alibaba.dubbo.common.bytecode;
import com.alibaba.dubbo.demo.provider.DemoDAO;
import com.alibaba.dubbo.demo.provider.DemoServiceImpl;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
public class Wrapper1 extends Wrapper implements ClassGenerator.DC
{
public static String[] pns;
public static Map pts;
public static String[] mns;
public static String[] dmns;
public static Class[] mts0;
public static Class[] mts1;
public static Class[] mts2;
public String[] getPropertyNames()
{
return pns;
}
public boolean hasProperty(String paramString)
{
return pts.containsKey(paramString);
}
public Class getPropertyType(String paramString)
{
return (Class)pts.get(paramString);
}
public String[] getMethodNames()
{
return mns;
}
public String[] getDeclaredMethodNames()
{
return dmns;
}
public void setPropertyValue(Object paramObject1, String paramString, Object paramObject2)
{
DemoServiceImpl w;
try
{
w = (DemoServiceImpl)paramObject1;
}
catch (Throwable localThrowable)
{
throw new IllegalArgumentException(localThrowable);
}
if (paramString.equals("test01"))
{
w.test01 = ((String)paramObject2);
return;
}
if (paramString.equals("demoDAO"))
{
localDemoServiceImpl.setDemoDAO((DemoDAO)paramObject2);
return;
}
throw new NoSuchPropertyException("Not found property \"" + paramString + "\" filed or setter method in class com.alibaba.dubbo.demo.provider.DemoServiceImpl.");
}
public Object getPropertyValue(Object paramObject, String paramString)
{
DemoServiceImpl w;
try
{
w = (DemoServiceImpl)paramObject;
}
catch (Throwable localThrowable)
{
throw new IllegalArgumentException(localThrowable);
}
if (paramString.equals("test01")) {
return localDemoServiceImpl.test01;
}
throw new NoSuchPropertyException("Not found property \"" + paramString + "\" filed or setter method in class com.alibaba.dubbo.demo.provider.DemoServiceImpl.");
}
public Object invokeMethod(Object paramObject, String paramString, Class[] paramArrayOfClass, Object[] paramArrayOfObject)
throws InvocationTargetException
{
DemoServiceImpl w;
try
{
w = (DemoServiceImpl)paramObject;
}
catch (Throwable localThrowable1)
{
throw new IllegalArgumentException(localThrowable1);
}
try
{
if ("sayHello".equals(paramString) && paramArrayOfClass.length == 1) {
return w.sayHello((String)paramArrayOfObject[0]);
}
if ("bye".equals(paramString) && paramArrayOfClass.length == 1)
{
w.bye((Object)paramArrayOfObject[0]);
return null;
}
if ("setDemoDAO".equals(paramString) && paramArrayOfClass.length == 1)
{
w.setDemoDAO((DemoDAO)paramArrayOfObject[0]);
return null;
}
}
catch (Throwable localThrowable2)
{
throw new InvocationTargetException(localThrowable2);
}
throw new NoSuchMethodException("Not found method \"" + paramString + "\" in class com.alibaba.dubbo.demo.provider.DemoServiceImpl.");
}
注:不同於生成的 proxy類,不實現 Service 接口類,而是在 #invokeMethod(paramObject, paramString, paramArrayOfClass, paramArrayOfObject) 方法,提供給 Invoker#invoke(invocation) 中調用,統一分發請求到 Service 對應的方法。從職能上來看,有一點像硬編碼的 Controller 。
3.ProxyFactory
3.1 AbstractProxyFactory
實現 ProxyFactory 接口,代理工廠抽象類。代碼如下:
/**
* AbstractProxyFactory
*
* 代理工廠抽象類
*/
public abstract class AbstractProxyFactory implements ProxyFactory {
public <T> T getProxy(Invoker<T> invoker) throws RpcException {
Class<?>[] interfaces = null;
// TODO 8022 芋艿
String config = invoker.getUrl().getParameter("interfaces");
if (config != null && config.length() > 0) {
String[] types = Constants.COMMA_SPLIT_PATTERN.split(config);
if (types != null && types.length > 0) {
interfaces = new Class<?>[types.length + 2];
interfaces[0] = invoker.getInterface();
interfaces[1] = EchoService.class;
for (int i = 0; i < types.length; i++) {
interfaces[i + 1] = ReflectUtils.forName(types[i]);
}
}
}
// 增加 EchoService 接口,用於回生測試。參見文檔《回聲測試》https://dubbo.gitbooks.io/dubbo-user-book/demos/echo-service.html
if (interfaces == null) {
interfaces = new Class<?>[]{invoker.getInterface(), EchoService.class};
}
return getProxy(invoker, interfaces);
}
public abstract <T> T getProxy(Invoker<T> invoker, Class<?>[] types);
3.2 JavassistProxyFactory
* JavassistRpcProxyFactory
*
* 基於 Javassist 代理工廠實現類
*/
public class JavassistProxyFactory extends AbstractProxyFactory {
@SuppressWarnings("unchecked")
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
// TODO Wrapper cannot handle this scenario correctly: the classname contains '$'
// TODO Wrapper類不能正確處理帶$的類名
final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
return new AbstractProxyInvoker<T>(proxy, type, url) {
@Override
protected Object doInvoke(T proxy, String methodName,
Class<?>[] parameterTypes,
Object[] arguments) throws Throwable {
return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
}
};
}
}
3.3 InvokerInvocationHandler
實現 java.lang.reflect.InvocationHandler 接口,代碼如下:
/**
* InvokerHandler
*/
public class InvokerInvocationHandler implements InvocationHandler {
/**
* Invoker 對象
*/
private final Invoker<?> invoker;
public InvokerInvocationHandler(Invoker<?> handler) {
this.invoker = handler;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
Class<?>[] parameterTypes = method.getParameterTypes();
// wait 等方法,直接反射調用
if (method.getDeclaringClass() == Object.class) {
return method.invoke(invoker, args);
}
// 基礎方法,不使用 RPC 調用
if ("toString".equals(methodName) && parameterTypes.length == 0) {
return invoker.toString();
}
if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
return invoker.hashCode();
}
if ("equals".equals(methodName) && parameterTypes.length == 1) {
return invoker.equals(args[0]);
}
// RPC 調用
return invoker.invoke(new RpcInvocation(method, args)).recreate();
}
}
4.AbstractProxyInvoker
實現 Invoker 接口,代理 Invoker 對象的抽象類。
4.1 屬性
/**
* 代理的對象,一般是 Service 實現對象
*/
private final T proxy;
/**
* 接口類型,一般是 Service 接口
*/
private final Class<T> type;
/**
* URL 對象,一般是暴露服務的 URL 對象
*/
private final URL url;
public AbstractProxyInvoker(T proxy, Class<T> type, URL url) {
if (proxy == null) {
throw new IllegalArgumentException("proxy == null");
}
if (type == null) {
throw new IllegalArgumentException("interface == null");
}
if (!type.isInstance(proxy)) { //
throw new IllegalArgumentException(proxy.getClass().getName() + " not implement interface " + type);
}
this.proxy = proxy;
this.type = type;
this.url = url;
}
4.2 屬性
public Result invoke(Invocation invocation) throws RpcException {
try {
return new RpcResult(doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments()));
} catch (InvocationTargetException e) {
return new RpcResult(e.getTargetException());
} catch (Throwable e) {
throw new RpcException("Failed to invoke remote proxy method " + invocation.getMethodName() + " to " + getUrl() + ", cause: " + e.getMessage(), e);
}
}
調用doInvoke抽象方法,執行調用,返回調用結果
/**
* 執行調用
*
* @param proxy 代理的對象
* @param methodName 方法名
* @param parameterTypes 方法參數類型數組
* @param arguments 方法參數數組
* @return 調用結果
* @throws Throwable 發生異常
*/
protected abstract Object doInvoke(T proxy, String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Throwable;
Wrapper 抽象類,用於創建某個對象的方法調用的包裝器,以避免反射調用,提高性能。即:
// 反射
Method#invoke(Object instance, Object[] args)
// 優化成===>
// Wrapper
Wrapper#invokeMethod(Object instance, String mn, Class<?>[] types, Object[] args)
5.1 getWrapper
/**
* get wrapper.
*
* 根據指定類,獲得 Wrapper 對象
*
* @param c Class instance. 指定類
* @return Wrapper instance(not null). Wrapper 對象
*/
public static Wrapper getWrapper(Class<?> c) {
// 判斷是否繼承 ClassGenerator.DC.class ,如果是,拿到父類,避免重複包裝
while (ClassGenerator.isDynamicClass(c)) // can not wrapper on dynamic class.
c = c.getSuperclass();
// 指定類爲 Object.class
if (c == Object.class)
return OBJECT_WRAPPER;
// 從緩存中獲得 Wrapper 對象
Wrapper ret = WRAPPER_MAP.get(c);
// 創建 Wrapper 對象,並添加到緩存
if (ret == null) {
ret = makeWrapper(c);
WRAPPER_MAP.put(c, ret);
}
return ret;
}
5.2 makeWrapper
創建 Wrapper 對象。代碼如下:
private static Wrapper makeWrapper(Class<?> c) {
// 非私有類
if (c.isPrimitive())
throw new IllegalArgumentException("Can not create wrapper for primitive type: " + c);
// 類名
String name = c.getName();
// 類加載器
ClassLoader cl = ClassHelper.getClassLoader(c);
// 設置屬性方法 `#setPropertyValue(o, n, v)` 的開頭的代碼
StringBuilder c1 = new StringBuilder("public void setPropertyValue(Object o, String n, Object v){ ");
// 獲得屬性方法 `#getPropertyValue(o, n)` 的開頭的代碼
StringBuilder c2 = new StringBuilder("public Object getPropertyValue(Object o, String n){ ");
// 調用方法 `#invokeMethod(o, n, p, v)` 的開頭的代碼
StringBuilder c3 = new StringBuilder("public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws " + InvocationTargetException.class.getName() + "{ ");
// 添加每個方法的,被調用對象的類型轉換的代碼
c1.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
c2.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
c3.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
// 屬性名與屬性名的集合,用於 `#hasProperty(...)` `#setPropertyValue(...)` `getPropertyValue(...)` 方法。
Map<String, Class<?>> pts = new HashMap<String, Class<?>>(); // <property name, property types>
// 方法簽名與方法對象的集合,用於 `#invokeMethod(..)` 方法。
Map<String, Method> ms = new LinkedHashMap<String, Method>(); // <method desc, Method instance>
// 方法名數組用於 `#getMethodNames()` 方法。
List<String> mns = new ArrayList<String>(); // method names.
// 定義的方法名數組,用於 `#getDeclaredMethodNames()` 方法。
List<String> dmns = new ArrayList<String>(); // declaring method names.
// 循環 public 屬性,添加每個屬性的設置和獲得分別到 `#setPropertyValue(o, n, v)` 和 `#getPropertyValue(o, n)` 的代碼
// get all public field.
for (Field f : c.getFields()) {
String fn = f.getName();
Class<?> ft = f.getType();
if (Modifier.isStatic(f.getModifiers()) || Modifier.isTransient(f.getModifiers())) // 排除 static 和 transient
continue;
c1.append(" if( $2.equals(\"").append(fn).append("\") ){ w.").append(fn).append("=").append(arg(ft, "$3")).append("; return; }");
c2.append(" if( $2.equals(\"").append(fn).append("\") ){ return ($w)w.").append(fn).append("; }");
// 添加到 `pts` 中
pts.put(fn, ft);
}
Method[] methods = c.getMethods();
// 如果有方法,添加 `#invokeMethod(o, n, p, v)` 的 try 的代碼
// get all public method.
boolean hasMethod = hasMethods(methods);
if (hasMethod) {
c3.append(" try{");
}
for (Method m : methods) {
// 跳過來自 Object 的內置方法
if (m.getDeclaringClass() == Object.class) //ignore Object's method.
continue;
String mn = m.getName(); // 方法名
// 使用方法名 + 方法參數長度來判斷
c3.append(" if( \"").append(mn).append("\".equals( $2 ) ");
int len = m.getParameterTypes().length;
c3.append(" && ").append(" $3.length == ").append(len);
// 若相同方法名存在多個,增加參數類型數組的比較判斷
boolean override = false;
for (Method m2 : methods) {
if (m != m2 && m.getName().equals(m2.getName())) {
override = true;
break;
}
}
if (override) {
if (len > 0) {
for (int l = 0; l < len; l++) {
c3.append(" && ").append(" $3[").append(l).append("].getName().equals(\"")
.append(m.getParameterTypes()[l].getName()).append("\")");
}
}
}
c3.append(" ) { ");
// 添加調用對象的對應方法的代碼
if (m.getReturnType() == Void.TYPE)
c3.append(" w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");").append(" return null;");
else
c3.append(" return ($w)w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");");
c3.append(" }");
// 添加到 `mns` 中
mns.add(mn);
// 添加到 `dmns` 中
if (m.getDeclaringClass() == c)
dmns.add(mn);
// 添加到 `ms` 中
ms.put(ReflectUtils.getDesc(m), m);
}
// 如果有方法,添加 `#invokeMethod(o, n, p, v)` 的 catch 的代碼
if (hasMethod) {
c3.append(" } catch(Throwable e) { ");
c3.append(" throw new java.lang.reflect.InvocationTargetException(e); ");
c3.append(" }");
}
// 添加 `#invokeMethod(o, n, p, v)` 的未匹配到方法的代碼
c3.append(" throw new " + NoSuchMethodException.class.getName() + "(\"Not found method \\\"\"+$2+\"\\\" in class " + c.getName() + ".\"); }");
// 循環 setting/getting 方法,添加每個屬性的設置和獲得分別到 `#setPropertyValue(o, n, v)` 和 `#getPropertyValue(o, n)` 的代碼
// deal with get/set method.
Matcher matcher;
for (Map.Entry<String, Method> entry : ms.entrySet()) {
String md = entry.getKey();
Method method = entry.getValue();
if ((matcher = ReflectUtils.GETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) {
String pn = propertyName(matcher.group(1));
c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }");
// 添加到 `pts` 中
pts.put(pn, method.getReturnType());
} else if ((matcher = ReflectUtils.IS_HAS_CAN_METHOD_DESC_PATTERN.matcher(md)).matches()) {
String pn = propertyName(matcher.group(1));
c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }");
// 添加到 `pts` 中
pts.put(pn, method.getReturnType());
} else if ((matcher = ReflectUtils.SETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) { // 不支持 public T setName(String name) { this.name = name; return this;} 這種返回 this 的形式。
Class<?> pt = method.getParameterTypes()[0];
String pn = propertyName(matcher.group(1));
c1.append(" if( $2.equals(\"").append(pn).append("\") ){ w.").append(method.getName()).append("(").append(arg(pt, "$3")).append("); return; }");
// 添加到 `pts` 中
pts.put(pn, pt);
}
}
c1.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }");
c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }");
// make class
long id = WRAPPER_CLASS_COUNTER.getAndIncrement();
// 創建 ClassGenerator 對象
ClassGenerator cc = ClassGenerator.newInstance(cl);
// 設置類名
cc.setClassName((Modifier.isPublic(c.getModifiers()) ? Wrapper.class.getName() : c.getName() + "$sw") + id);
// 設置父類爲 Wrapper.class
cc.setSuperClass(Wrapper.class);
// 添加構造方法,參數 空
cc.addDefaultConstructor();
// 添加靜態屬性 `pns` 的代碼
cc.addField("public static String[] pns;"); // property name array.
// 添加靜態屬性 `pts` 的代碼
cc.addField("public static " + Map.class.getName() + " pts;"); // property type map.
// 添加靜態屬性 `pts` 的代碼
cc.addField("public static String[] mns;"); // all method name array.
// 添加靜態屬性 `dmns` 的代碼
cc.addField("public static String[] dmns;"); // declared method name array.
// 添加靜態屬性 `mts` 的代碼。每個方法的參數數組。
for (int i = 0, len = ms.size(); i < len; i++)
cc.addField("public static Class[] mts" + i + ";");
// ======= 添加抽象方法的實現,到 `cc` 中
// 添加 `#getPropertyNames()` 的代碼到 `cc`
cc.addMethod("public String[] getPropertyNames(){ return pns; }");
// 添加 `#hasProperty(n)` 的代碼到 `cc`
cc.addMethod("public boolean hasProperty(String n){ return pts.containsKey($1); }");
// 添加 `#getPropertyType(n)` 的代碼到 `cc`
cc.addMethod("public Class getPropertyType(String n){ return (Class)pts.get($1); }");
// 添加 `#getMethodNames()` 的代碼到 `cc`
cc.addMethod("public String[] getMethodNames(){ return mns; }");
// 添加 `#getDeclaredMethodNames()` 的代碼到 `cc`
cc.addMethod("public String[] getDeclaredMethodNames(){ return dmns; }");
// 添加 `#setPropertyValue(o, n, v)` 的代碼到 `cc`
cc.addMethod(c1.toString());
// 添加 `#getPropertyValue(o, n)` 的代碼到 `cc`
cc.addMethod(c2.toString());
// 添加 `#invokeMethod(o, n, p, v)` 的代碼到 `cc`
cc.addMethod(c3.toString());
try {
// 生成類
Class<?> wc = cc.toClass();
// 反射,設置靜態變量的值
// setup static field.
wc.getField("pts").set(null, pts);
wc.getField("pns").set(null, pts.keySet().toArray(new String[0]));
wc.getField("mns").set(null, mns.toArray(new String[0]));
wc.getField("dmns").set(null, dmns.toArray(new String[0]));
int ix = 0;
for (Method m : ms.values())
wc.getField("mts" + ix++).set(null, m.getParameterTypes());
// 創建對象
return (Wrapper) wc.newInstance();
} catch (RuntimeException e) {
throw e;
} catch (Throwable e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
// 釋放資源
cc.release();
ms.clear();
mns.clear();
dmns.clear();
}
}
6. Proxy
代理抽象類,用於創建 Proxy 和 proxy 對象。
6.1 getProxy
獲取Proxy
/**
* Get proxy.
*
* @param ics interface class array.
* @return Proxy instance.
*/
public static Proxy getProxy(Class<?>... ics) {
return getProxy(ClassHelper.getClassLoader(Proxy.class), ics);
}
6.2 getProxy
/**
* Get proxy.
*
* @param cl class loader.
* @param ics interface class array.
* @return Proxy instance.
*/
public static Proxy getProxy(ClassLoader cl, Class<?>... ics) {
// 校驗接口超過上限
if (ics.length > 65535)
throw new IllegalArgumentException("interface limit exceeded");
// use interface class name list as key.
StringBuilder sb = new StringBuilder();
for (int i = 0; i < ics.length; i++) {
String itf = ics[i].getName();
// 校驗是否爲接口
if (!ics[i].isInterface())
throw new RuntimeException(itf + " is not a interface.");
// 加載接口類
Class<?> tmp = null;
try {
tmp = Class.forName(itf, false, cl);
} catch (ClassNotFoundException e) {
}
if (tmp != ics[i]) // 加載接口類失敗
throw new IllegalArgumentException(ics[i] + " is not visible from class loader");
sb.append(itf).append(';');
}
// use interface class name list as key.
String key = sb.toString();
// get cache by class loader.
Map<String, Object> cache;
synchronized (ProxyCacheMap) {
cache = ProxyCacheMap.get(cl);
if (cache == null) {
cache = new HashMap<String, Object>();
ProxyCacheMap.put(cl, cache);
}
}
// 獲得 Proxy
Proxy proxy = null;
synchronized (cache) {
do {
// 從緩存中獲取 Proxy
Object value = cache.get(key);
if (value instanceof Reference<?>) {
proxy = (Proxy) ((Reference<?>) value).get();
if (proxy != null)
return proxy;
}
// 緩存中不存在,設置生成 Proxy 代碼標記。創建中時,其他創建請求等待,避免併發。
if (value == PendingGenerationMarker) {
try {
cache.wait();
} catch (InterruptedException e) {
}
} else {
cache.put(key, PendingGenerationMarker);
break;
}
}
while (true);
}
long id = PROXY_CLASS_COUNTER.getAndIncrement();
String pkg = null;
ClassGenerator ccp = null, // proxy class generator
ccm = null; // Proxy class generator
try {
// 創建 proxy 代碼生成器
ccp = ClassGenerator.newInstance(cl);
Set<String> worked = new HashSet<String>(); // 已處理方法簽名集合。key:方法簽名
List<Method> methods = new ArrayList<Method>(); // 已處理方法集合。
// 處理接口
for (int i = 0; i < ics.length; i++) {
// 非 public 接口,使用接口包名
if (!Modifier.isPublic(ics[i].getModifiers())) {
String npkg = ics[i].getPackage().getName();
if (pkg == null) {
pkg = npkg;
} else {
if (!pkg.equals(npkg)) // 實現了兩個非 public 的接口,
throw new IllegalArgumentException("non-public interfaces from different packages");
}
}
// 添加接口
ccp.addInterface(ics[i]);
// 處理接口方法
for (Method method : ics[i].getMethods()) {
// 添加方法簽名到已處理方法簽名集合
String desc = ReflectUtils.getDesc(method);
if (worked.contains(desc))
continue;
worked.add(desc);
// 生成接口方法實現代碼
int ix = methods.size();
Class<?> rt = method.getReturnType();
Class<?>[] pts = method.getParameterTypes();
StringBuilder code = new StringBuilder("Object[] args = new Object[").append(pts.length).append("];");
for (int j = 0; j < pts.length; j++)
code.append(" args[").append(j).append("] = ($w)$").append(j + 1).append(";");
code.append(" Object ret = handler.invoke(this, methods[" + ix + "], args);");
if (!Void.TYPE.equals(rt))
code.append(" return ").append(asArgument(rt, "ret")).append(";");
methods.add(method);
// 添加方法
ccp.addMethod(method.getName(), method.getModifiers(), rt, pts, method.getExceptionTypes(), code.toString());
}
}
// 設置包路徑
if (pkg == null)
pkg = PACKAGE_NAME;
// ===== 設置 proxy 代碼生成的屬性 =====
// create ProxyInstance class.
// 設置類名
String pcn = pkg + ".proxy" + id;
ccp.setClassName(pcn);
// 添加靜態屬性 methods
ccp.addField("public static java.lang.reflect.Method[] methods;");
// 添加屬性 handler
ccp.addField("private " + InvocationHandler.class.getName() + " handler;");
// 添加構造方法,參數 handler
ccp.addConstructor(Modifier.PUBLIC, new Class<?>[]{InvocationHandler.class}, new Class<?>[0], "handler=$1;");
// 添加構造方法,參數 空
ccp.addDefaultConstructor();
// 生成類
Class<?> clazz = ccp.toClass();
// 設置靜態屬性 methods
clazz.getField("methods").set(null, methods.toArray(new Method[0]));
// create Proxy class.
// 創建 Proxy 代碼生成器
String fcn = Proxy.class.getName() + id;
ccm = ClassGenerator.newInstance(cl);
// 設置類名
ccm.setClassName(fcn);
// 添加構造方法,參數 空
ccm.addDefaultConstructor();
// 設置父類爲 Proxy.class
ccm.setSuperClass(Proxy.class);
// 添加方法 #newInstance(handler)
ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }");
// 生成類
Class<?> pc = ccm.toClass();
// 創建 Proxy 對象
proxy = (Proxy) pc.newInstance();
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
// release ClassGenerator
if (ccp != null)
ccp.release();
if (ccm != null)
ccm.release();
// 喚醒緩存 wait
synchronized (cache) {
if (proxy == null)
cache.remove(key);
else
cache.put(key, new WeakReference<Proxy>(proxy));
cache.notifyAll();
}
}
return proxy;
}