20.反射调用是如何优化的?Wrapper的作用是什么?
反编译生成的代码
对于动态代码生成的class可以写出到本地,办法是:
在com.alibaba.dubbo.common.bytecode.ClassGenerator.mCtc这个实例有
javassist.CtClass.writeFile(String)方法,可以在com.alibaba.dubbo.common.bytecode.ClassGenerator.toClass()结束时将生成的class写出到本地。
对于动态代码生成的class可以用procyon反编译器反编译,命令行形式的,JD有点力不从心。
也可以用阿尔特斯等诊断工具导出。
// com.alibaba.dubbo.common.bytecode.ClassGenerator.mCtc
// mCtc.writeFile("d:/")
//D:\002.tools>java -jar procyon-decompiler-0.5.36.jar //d:\com\alibaba\dubbo\common\bytecode\Wrapper0.class
//
// Decompiled by Procyon v0.5.36
//
package com.alibaba.dubbo.common.bytecode;
import java.lang.reflect.InvocationTargetException;
import org.simonme.dubbo.demo.provider.service.HelloService;
import java.util.Map;
public class Wrapper0 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 String[] getPropertyNames() {
return Wrapper0.pns;
}
public boolean hasProperty(final String s) {
return Wrapper0.pts.containsKey(s);
}
public Class getPropertyType(final String s) {
return Wrapper0.pts.get(s);
}
public String[] getMethodNames() {
return Wrapper0.mns;
}
public String[] getDeclaredMethodNames() {
return Wrapper0.dmns;
}
public void setPropertyValue(final Object o, final String s, final Object o2) {
try {
final HelloService helloService = (HelloService)o;
}
catch (Throwable t) {
throw new IllegalArgumentException(t);
}
throw new NoSuchPropertyException(new StringBuffer().append("Not found property \"").append(s).append("\" filed or setter method in class org.simonme.dubbo.demo.provider.service.HelloService.").toString());
}
public Object getPropertyValue(final Object o, final String s) {
try {
final HelloService helloService = (HelloService)o;
}
catch (Throwable t) {
throw new IllegalArgumentException(t);
}
throw new NoSuchPropertyException(new StringBuffer().append("Not found property \"").append(s).append("\" filed or setter method in class org.simonme.dubbo.demo.provider.service.HelloService.").toString());
}
public Object invokeMethod(final Object o, final String s, final Class[] array, final Object[] array2) throws InvocationTargetException {
HelloService helloService;
try {
helloService = (HelloService)o;
}
catch (Throwable t) {
throw new IllegalArgumentException(t);
}
try {
if ("sayHello".equals(s) && array.length == 1) {
helloService.sayHello((String)array2[0]);
return null;
}
}
catch (Throwable t2) {
throw new InvocationTargetException(t2);
}
throw new NoSuchMethodException(new StringBuffer().append("Not found method \"").append(s).append("\" in class org.simonme.dubbo.demo.provider.service.HelloService.").toString());
}
}
invokeMethod 实现了方法调用
// D:\002.tools>java -jar procyon-decompiler-0.5.36.jar // d:\com\alibaba\dubbo\common\bytecode\Wrapper1.class
//
// Decompiled by Procyon v0.5.36
//
package com.alibaba.dubbo.common.bytecode;
import java.lang.reflect.InvocationTargetException;
import org.simonme.dubbo.demo.provider.service.DepenededService;
import org.simonme.dubbo.demo.provider.service.impl.HelloServiceSlowImpl;
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 Wrapper1.pns;
}
public boolean hasProperty(final String s) {
return Wrapper1.pts.containsKey(s);
}
public Class getPropertyType(final String s) {
return Wrapper1.pts.get(s);
}
public String[] getMethodNames() {
return Wrapper1.mns;
}
public String[] getDeclaredMethodNames() {
return Wrapper1.dmns;
}
public void setPropertyValue(final Object o, final String s, final Object o2) {
HelloServiceSlowImpl helloServiceSlowImpl;
try {
helloServiceSlowImpl = (HelloServiceSlowImpl)o;
}
catch (Throwable t) {
throw new IllegalArgumentException(t);
}
if (s.equals("depenededService")) {
helloServiceSlowImpl.setDepenededService((DepenededService)o2);
return;
}
throw new NoSuchPropertyException(new StringBuffer().append("Not found property \"").append(s).append("\" filed or setter method in class org.simonme.dubbo.demo.provider.service.impl.HelloServiceSlowImpl.").toString());
}
public Object getPropertyValue(final Object o, final String s) {
HelloServiceSlowImpl helloServiceSlowImpl;
try {
helloServiceSlowImpl = (HelloServiceSlowImpl)o;
}
catch (Throwable t) {
throw new IllegalArgumentException(t);
}
if (s.equals("depenededService")) {
return helloServiceSlowImpl.getDepenededService();
}
throw new NoSuchPropertyException(new StringBuffer().append("Not found property \"").append(s).append("\" filed or setter method in class org.simonme.dubbo.demo.provider.service.impl.HelloServiceSlowImpl.").toString());
}
public Object invokeMethod(final Object o, final String s, final Class[] array, final Object[] array2) throws InvocationTargetException {
HelloServiceSlowImpl helloServiceSlowImpl;
try {
helloServiceSlowImpl = (HelloServiceSlowImpl)o;
}
catch (Throwable t) {
throw new IllegalArgumentException(t);
}
try {
if ("sayHello".equals(s) && array.length == 1) {
helloServiceSlowImpl.sayHello((String)array2[0]);
return null;
}
if ("getDepenededService".equals(s) && array.length == 0) {
return helloServiceSlowImpl.getDepenededService();
}
if ("setDepenededService".equals(s) && array.length == 1) {
helloServiceSlowImpl.setDepenededService((DepenededService)array2[0]);
return null;
}
}
catch (Throwable t2) {
throw new InvocationTargetException(t2);
}
throw new NoSuchMethodException(new StringBuffer().append("Not found method \"").append(s).append("\" in class org.simonme.dubbo.demo.provider.service.impl.HelloServiceSlowImpl.").toString());
}
}
解释
wrap的作用 我的理解是将反射(读取字段、调用业务方法) 转成 直接调用,同时以统一的调用接口对外暴露
JavassistProxyFactory.getInvoker
先用Wrapper机制wrapper一下 。 对于生成的Wrapper实例再怎么放到调用链中和其他Invoker实例怎么相互对接并产生作用可以参见《调用链如何构建的?ProtocolFilterWrapper等分析》。
getPropertyValue与setPropertyValue在你的业务服务实现类中如果实例字段,比如依赖其他服务,这个生成的方法就会起作用了,可以参见上面反编译的第二段代码,上面贴了两段反编译的代码对比也是这个目的。
顺带说一句,JavassistProxyFactory 除了在其getInvoker对接wrapper机制完成上述事情之外,还通过其getProxy方法结合其父类的getProxy方法将EchoService回声服务自动织入进业务服务实现中。
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!