dubbo中使用动态代理
生活随笔
收集整理的這篇文章主要介紹了
dubbo中使用动态代理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
dubbo的動態代理也是只能代理接口
源碼入口在JavassistProxyFactory中
public class JavassistProxyFactory extends AbstractProxyFactory {@Override@SuppressWarnings("unchecked")public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));}@Overridepublic <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {// TODO Wrapper cannot handle this scenario correctly: the classname contains '$'final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);return new AbstractProxyInvoker<T>(proxy, type, url) {@Overrideprotected Object doInvoke(T proxy, String methodName,Class<?>[] parameterTypes,Object[] arguments) throws Throwable {return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);}};} }先寫個demo
接口
public interface BasePerson {void doSth() ;String getSth() ; }接口實現類
public class Person implements BasePerson {@Overridepublic void doSth() {System.out.println("Person 正在 努力工作");}@Overridepublic String getSth() {System.out.println("person 正在 獲取報酬");return "good men";} }寫一個InvocationHandler
public class MyInvocationHandler implements InvocationHandler {Object targetObj;public MyInvocationHandler(Object obj) {targetObj = obj;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("代理前置");Object invoke = method.invoke(targetObj, args);System.out.println("代理后置");return invoke;} }測試類
public class ProxyTest {public static void main(String[] args) {Person person = new Person();Class<?>[] interfaces = Person.class.getInterfaces();BasePerson proxyperson = (BasePerson) Proxy.getProxy(interfaces).newInstance(new MyInvocationHandler(person));String sth = proxyperson.getSth();System.out.println(sth);} }控制臺打印
代理前置 person 正在 獲取報酬 代理后置 good men源碼分析
ClassHelper
// 優先獲取當前線程的類加載器 public static ClassLoader getClassLoader(Class<?> cls) {ClassLoader cl = null;try {cl = Thread.currentThread().getContextClassLoader();} catch (Throwable ex) {// Cannot access thread context ClassLoader - falling back to system class loader...}if (cl == null) {//沒有線程上下文的類加載器,使用接口的類加載器cl = cls.getClassLoader();}return cl; }Proxy
public static Proxy getProxy(Class<?>... ics) {//先獲取類加載器return getProxy(ClassHelper.getClassLoader(Proxy.class), ics); }Proxy 主要是這個方法
public static Proxy getProxy(ClassLoader cl, Class<?>... ics) {if (ics.length > 65535)throw new IllegalArgumentException("interface limit exceeded");//記載被代理類接口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(';');}// 接口集的名字作為keyString key = sb.toString();// 使用類加載器獲取緩存Map<String, Object> cache;synchronized (ProxyCacheMap) {cache = ProxyCacheMap.get(cl);if (cache == null) {cache = new HashMap<String, Object>();ProxyCacheMap.put(cl, cache);}}Proxy proxy = null;synchronized (cache) {do {// 從緩存中獲取Object value = cache.get(key);if (value instanceof Reference<?>) {proxy = (Proxy) ((Reference<?>) value).get();if (proxy != null)return proxy;}if (value == PendingGenerationMarker) {try {cache.wait();} catch (InterruptedException e) {}} else {// 添加到緩存(value是一個標識)cache.put(key, PendingGenerationMarker);break;}}while (true);}//自增idlong id = PROXY_CLASS_COUNTER.getAndIncrement();//以下就是使用javassist拼裝代理類String pkg = null;ClassGenerator ccp = null, ccm = null;try {ccp = ClassGenerator.newInstance(cl);Set<String> worked = new HashSet<String>();List<Method> methods = new ArrayList<Method>();for (int i = 0; i < ics.length; i++) {if (!Modifier.isPublic(ics[i].getModifiers())) {String npkg = ics[i].getPackage().getName();if (pkg == null) {pkg = npkg;} else {if (!pkg.equals(npkg))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;// create ProxyInstance class.String pcn = pkg + ".proxy" + id;ccp.setClassName(pcn);ccp.addField("public static java.lang.reflect.Method[] methods;");ccp.addField("private " + InvocationHandler.class.getName() + " handler;");ccp.addConstructor(Modifier.PUBLIC, new Class<?>[]{InvocationHandler.class}, new Class<?>[0], "handler=$1;");ccp.addDefaultConstructor();Class<?> clazz = ccp.toClass();clazz.getField("methods").set(null, methods.toArray(new Method[0]));// create Proxy class.String fcn = Proxy.class.getName() + id;ccm = ClassGenerator.newInstance(cl);ccm.setClassName(fcn);ccm.addDefaultConstructor();ccm.setSuperClass(Proxy.class);ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }");Class<?> pc = ccm.toClass();proxy = (Proxy) pc.newInstance();} catch (RuntimeException e) {throw e;} catch (Exception e) {throw new RuntimeException(e.getMessage(), e);} finally {// release ClassGeneratorif (ccp != null)ccp.release();if (ccm != null)ccm.release();synchronized (cache) {if (proxy == null)cache.remove(key);elsecache.put(key, new WeakReference<Proxy>(proxy));cache.notifyAll();}}return proxy; }得到編譯的class文件
//如果接口是public修飾的 就在debug的時候使用這個能在E盤下生成class文件,e:/com/alibaba/dubbo/common/bytecode/proxy0/proxy0.class ccm.getClassPool().get("com.alibaba.dubbo.common.bytecode.proxy0").debugWriteFile("e:\\") //如果接口沒有被public修飾 debug的時候可以用以下方式獲取class文件 ccp.getClassPool().get("per.qiao.util.proxy0").debugWriteFile("e:\\") ccm.getClassPool().get("per.qiao.util.proxy0").debugWriteFile("e:\\")debug截圖
編譯后的文件proxy0.class
package com.alibaba.dubbo.common.bytecode;import com.alibaba.dubbo.common.bytecode.ClassGenerator.DC; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import per.qiao.util.BasePerson;public class proxy0 implements DC, BasePerson {public static Method[] methods;private InvocationHandler handler;public String getSth() {Object[] var1 = new Object[0];Object var2 = this.handler.invoke(this, methods[0], var1);return (String)var2;}public void doSth() {Object[] var1 = new Object[0];this.handler.invoke(this, methods[1], var1);}public proxy0() {}public proxy0(InvocationHandler var1) {this.handler = var1;} }轉載于:https://www.cnblogs.com/qiaozhuangshi/p/11185098.html
總結
以上是生活随笔為你收集整理的dubbo中使用动态代理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU 3926 图的同构
- 下一篇: spring中使用动态代理(AOP)