当前位置: 首页 > news >正文

网络营销基础战略优化技术基础

网络营销基础战略,优化技术基础,建设母婴网站的总结,太原自助建站系统javassist介绍 Javassist是一个开源的分析、编辑和创建Java字节码的类库,主要优点是简单,不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。 apisdk应用javassist 在apisdk中主要依靠javassist增强开发者声明的开放…

javassist介绍

Javassist是一个开源的分析、编辑和创建Java字节码的类库,主要优点是简单,不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。

apisdk应用javassist

在apisdk中主要依靠javassist增强开发者声明的开放接口,例如开发者声明接口:

public interface TestOpenapiServiceV2 {@RequestMapping(path = "openapi/{group_id}/users", method = RequestMethod.GET)List<UserVO> getList(@Path("group_id") String groupId);
}

应用启动时扫描的TestOpenapiServiceV2会被javassist增强,生成新的内存类,如下:

public interface $TestOpenapiServiceV2 {@RequestMapping(path = "openapi/{group_id}/users", method = RequestMethod.GET)List<UserVO> getList(@Path("group_id") String groupId, SdkContext sdkContext);
}

内存类的命名 = $ + 原始类名,同时复制所有原始方法,并判断原始方法是否存在SdkContext.class,如果不存在,则需要在虚拟方法上添加SdkContext方法参数。

上面简单的描述了javassist做了哪些事情,你可能会想,这有啥难度,直接调用javassist的api拷贝类和方法就行了。然而实际的开发过程中,踩了很多坑,巩固了Class类文件结构的知识点。

《深入理解Java虚拟机》这本书有讲“Class类文件结构”,里面有“字段表集合”、“方法表集合”、“属性表集合”,我相信大部分开发者只是在书面上看过,觉得这些东西太抽象了,不知道底层表示了什么,希望通过javassist,你可以了解一些底层的表现。

核心代码

EnhanceProxyInstance 代理对象包装

扫描到开放接口(A)后,交给EnhanceProxyInstance处理Class的增强得到新接口(B),然后调用apisdk生成B的代理对象,EnhanceProxyInstance可以看成A和B的映射封装,JdkDynamicAopProxy#invoke方法获取B的代理对象并执行远程调用。

EnhanceProxyInstance代码如下:

public class EnhanceProxyInstance {// 开放接口真正增强的执行对象private OpenApiEnhance openApiEnhance;// javassist 增强后的代理对象private Object proxyBean;// 构造器调用 OpenApiEnhance 进行 javassist 增强,SdkManager 生成增强后的代理对象public EnhanceProxyInstance(Class openApiInterface) {this.openApiEnhance = new OpenApiEnhance(openApiInterface);proxyBean = SdkManager.get(this.openApiEnhance.getEnhanceInterface());}// 获取代理对象,JdkDynamicAopProxy 中通过 Aop 的配置对象调用此方法获取代理对象public Object getProxyBean() {return proxyBean;}
}

OpenApiEnhance 类增强

OpenApiEnhance#create$0是表现javassist的入口,完成了原方法的拷贝,添加方法参数,填充方法运行时注解、注解范型、方法参数范型等。

OpenApiEnhance#create$0代码如下:

private Class create$0(Class openApiInterface) {// 获取原始类的 CtClassthis.sourceCtClass = EnhanceUtil.pool.getCtClass(openApiInterface.getName());// 拷贝原始类,生成新的内存类,命名:$ + 原始类的名称CtClass targetCtClass = EnhanceUtil.copyCtClass(openApiInterface);if (targetCtClass.isFrozen()) {targetCtClass.defrost();}CtMethod[] methods = sourceCtClass.getDeclaredMethods();// 获取 SdkContext 的 CtClassCtClass sdkContext = EnhanceUtil.pool.getCtClass(EnhanceUtil.SDK_CONTEXT_CLASS);// 获取原始类的常量池// 知识点:《深入理解Java虚拟机》常量池ConstPool constPool = targetCtClass.getClassFile().getConstPool();// 遍历原始类的所有方法,逐个拷贝,添加 SdkContext 方法参数for (CtMethod sourceCtMethod : methods) {Method sourceMethod = openApiInterface.getDeclaredMethod(sourceCtMethod.getName(), getParameterTypes(sourceCtMethod));// 拷贝原始方法,注意:拷贝得到的方法不带注解CtMethod targetCtMethod = CtNewMethod.copy(sourceCtMethod, targetCtClass, null);// 判断是否需要自动注入 SdkContext.classboolean needAutoType = needAutoType(sourceMethod);if (needAutoType) {targetCtMethod.addParameter(sdkContext);}// 知识点:《深入理解Java虚拟机》Class文件结构中的 method_info 方法表集合MethodInfo methodInfo = targetCtMethod.getMethodInfo();// 知识点:《深入理解Java虚拟机》Class文件结构中的 attribute_info 属性表集合// Class 文件、字段表、方法表都有自己都属性表集合List<AttributeInfo> attributes = sourceCtMethod.getMethodInfo().getAttributes();for (AttributeInfo attribute : attributes) {// 运行时可见的注解,实际上就是运行时就是进行反射调用可见的// 知识点:《深入理解Java虚拟机》属性表的 RuntimeVisibleAnnotationsif (attribute instanceof AnnotationsAttribute) {// 拷贝方法上的注解AttributeInfo methodAnnotation = attribute.copy(constPool, null);methodInfo.addAttribute(methodAnnotation);}// Java具有范型擦除,范型情况下的方法签名,记录了真实的类型// 知识点:《深入理解Java虚拟机》属性表的  Signatureif (attribute instanceof SignatureAttribute) {// 范型处理AttributeInfo methodAnnotation = attribute.copy(constPool, null);methodInfo.addAttribute(methodAnnotation);}if (attribute instanceof ParameterAnnotationsAttribute) {// 参数注解// 注意:因为手动新增了 SdkContext 方法参数,不能像方法注解一样直接拷贝,会抛出方法参数不匹配的异常EnhanceUtil.copyParameterAnnotationsAttribute(constPool, methodInfo, attribute, needAutoType);}}String newSignature = methodInfo.toString();targetKeySourceMethodMap.put(newSignature, sourceMethod);targetCtClass.addMethod(targetCtMethod);}Class<?> newClass = targetCtClass.toClass();this.targetCtClass = targetCtClass;return newClass;
}

AccessorProxyBean 代理对象注册Spring入口

Spring扫描到BeanDefinition时,替换了beanClass,替换的就是AccessorProxyBean,它实现了Spring的FactoryBean,getObject方法触发创建EnhanceProxyInstance,最终生成的代理对象被Spring管理。

public class AccessorProxyBean<T> implements FactoryBean<T>, ApplicationContextAware, InitializingBean,ApplicationListener<ApplicationEvent> {// 原始 bean classprivate Class<T> sourceClass;// 代理 beanprivate T proxyBean;// 生成代理对象的工厂private AccessorFactory accessorFactory;public AccessorProxyBean(Class<T> sourceClass) {this.sourceClass = sourceClass;}@Overridepublic T getObject() throws Exception {if (Objects.isNull(accessorFactory)) {afterPropertiesSet();}if (Objects.isNull(proxyBean)) {// 初始化 open apiproxyBean = accessorFactory.create(sourceClass);}return proxyBean;}
}

AccessorFactory 代理对象生成工厂

ApiSdkAccessorFactory是AccessorFactory的唯一实现,同时生成A和B的代理对象,A由Spring管理,B由EnhanceProxyInstance缓存。

代码如下:

public class ApiSdkAccessorFactory implements AccessorFactory {private GlobalConfiguration globalConfiguration;public ApiSdkAccessorFactory(GlobalConfiguration globalConfiguration) {this.globalConfiguration = globalConfiguration;}@Overridepublic <T> T create(Class<T> openApiInterface) {// javassist 调用入口,存储增强类的代理对象EnhanceProxyInstance enhanceProxyInstance = new EnhanceProxyInstance(openApiInterface);// 原始接口的包装,生成的代理对象由 Spring 管理,代理对象的方法之前时会由 Aop 拦截ProxyFactory proxyFactory = new ProxyFactory(enhanceProxyInstance);List<Advice> advices = globalConfiguration.getAdvices();for (Advice advice : advices) {proxyFactory.addAdvice(advice);}return (T) proxyFactory.getProxy();}
}
http://www.yayakq.cn/news/109825/

相关文章:

  • 苏州网站建设方案扫码点餐小程序怎么做
  • 苏州网站建设科技有限公司wordpress 主题 家居
  • 我的网站在百度搜不到了静态网页设计心得体会
  • 抚顺市营商环境建设局网站wordpress实现瀑布流
  • 安徽长江建设集团有限公司网站wordpress中英网站插件
  • 广州骏域网站做企业网站怎么备案
  • ASP.NET2.0网站开发全程解析详情页设计逻辑
  • 企业建设网站预算摄影网站设计模板
  • 网站网页设计中怎么添加页码信息网站开发模式分为
  • 个人网站备案填写建湖人才网官网登录
  • 专业的公司网站开发电商平台哪个好做
  • 更新网站 是否要重启iis贵州三线建设博物馆网站
  • 爱站网能不能挖掘关键词出台网站集约化建设通知
  • 青岛建站通服饰的网站建设
  • 网站建设流程所用工具软件开发用什么软件编程
  • 松江做网站费用wordpress 海 主题
  • 进口彩妆做的好的网站行业网站维护
  • 黑龙江做网站的公司google网页版登录入口
  • 南宁企业网站建站模板福州网站建设印秀
  • 网站建设预算知乎出名的网站有哪些
  • 长沙门户网站有哪些网站建设的业务范围
  • 住房城乡建设干部学院网站勒流网站建设
  • 室内设计师的网站郑州seo顾问阿亮
  • 游戏开发网站开发wordpress html 标签
  • html如何做网站网站演示网站代码
  • 手机网站建设制作公司工程施工项目管理软件
  • 太原网站优化培训做网站教程 第一课
  • 网站问卷调查怎么做建站国外百元服务器
  • 南昌网站建设58如何在网上推广项目
  • 淘宝搜券的网站怎么做网站开发文案模板