Java 温故知新

动态 Java

Java 动态性,正在不断补充。如果用 JS 这些动态语言那当然简单。

选型 Java 动态代理 JavaAgent/Instrument/动态编译 ASM cglib Javassist
是否 Java 自带 yes yes no no no
使用场景 监控和控制虚拟机的行为 字节码生成框架 字节码生成框架,基于 ASM
优点 自带 快速 快速简单 快速简单
缺点 对 main方法或jar 实施 需要接口,语法晦涩 过于底层,需要字节码知识
官网 n/a n/a https://asm.ow2.io/ https://github.com/cglib/cglib http://www.javassist.org/

Ref:

  • Java APT
  • JavaPoet (https://github.com/square/javapoet)生成 Java 文件而不是字节码
  • https://blog.csdn.net/u010072711/article/details/77040159
  • https://www.jianshu.com/p/5514cf705666
  • https://blog.csdn.net/zhuoxiuwu/article/details/78619645
  • https://blog.csdn.net/qq_32115439/article/details/78361596
  • 组件化 https://www.jianshu.com/p/0d45f2a894ba
  • MethodHandle,类似于反射中的Method类,但它比Method类要更加灵活和轻量级 https://blog.csdn.net/sunjiaminaini/article/details/76976694 https://cloud.tencent.com/developer/article/1005920

热加载

选型:

  • JRebel 收费,要破解,麻烦
  • Spring-loaded,不太清楚,是否依赖 Spring?
  • 使用 jdb,自带的命令行调试工具,不太清楚
  • 使用 idea,不太清楚,我用 Eclipse 的,是否自带不需要插件?
  • OSGi + Gradle osgi-run plugin + Apache Felix,老外介绍的,貌似比较麻烦,不清楚
  • 基于 Jetty 的热加载,Tomcat 不行,可参考 JFinal 实现,另外 Act 也实现了热加载
  • DCEVM+ HotSwapAgent 开源,不知道坑怎么样,打算试试

两篇介绍热加载不错 的文章

IOC 注解

Spring JSR330 Ajaxjs
@Component @Named @Resources
@Autowired @Inject @Bean
@Qualifier @Named @Resources

基于包的模块

一个包是一个代码集合,对外暴露的只是在这个包里面的一个接口和实现,其他不可见

Javassist

添加一个 setter

ClassPool pool = ClassPool.getDefault();
CtClass cc;
try {
	cc = pool.get("com.ajaxjs.ioc.Hi");
//	CtMethod m = CtNewMethod.make("public void setPerson(com.ajaxjs.ioc.Person person) { this.person = person; }", cc);
//	cc.addMethod(m);
  	// 或者
	CtField f1 = new CtField(pool.get("com.ajaxjs.ioc.Person"), "person", cc);
	cc.addMethod(CtNewMethod.setter("setPerson", f1));

//	Class<?> c = cc.toClass(this.getClass().getClassLoader());
	cc.toClass();
} catch (NotFoundException | CannotCompileException e) {
	e.printStackTrace();
}

修改的前提即是当前修改的类还没有被当前 jvm 加载,如果当前的类已经被加载,则不能修改。需要注意的是,在调用 ctClass.toClass() 时,会加载此类,如果此类在之前已经被加载过,则会报一个 duplicate load 的错误,表示不能重复加载一个类。所以,修改方法的实现必须在修改的类加载之前进行。即使不调用 toClass,那么如果当前修改的类已经加载,那么修改方法实现,同样不起作用,即修改一个已经加载的类(不论是修改静态方法,还是修改动态方法)是没有任何效果的。修改之前必须在类加载之前进行。

怎么动态重载Class?
如果 JVM 运行时开启 JPDA(Java Platform Debugger Architecture),则 Class 是运行被动态重新载入的。具体方式可以参考 java.lang.Instrument。javassist也提供了一个运行期重载 Class 的方法,具体可以看API 中的javassist.tools.HotSwapper。参考:http://www.cnblogs.com/zhjh256/p/6286198.html

获取方法名称

Java 8 的反射也可以,但是要打开编译开关,比较麻烦的说。Javassist 则不存在这个问题,对于任意方法,都能正确的获取其参数的参数名。参见 LocalVariableAttribute。

  • https://blog.csdn.net/21aspnet/article/details/81671777
  • https://www.cnblogs.com/sunfie/p/5154246.html
  • https://www.cnblogs.com/hucn/p/3636912.html

动态添加、修改 Java 注解

怎么动态添加、修改 Java 注解?有人说用动态代理,其实不必,因为动态代理需要实现代理的接口,比较不方便;有人说用 Javassist,那是方便,不过也要加 jar 包;其实最省事的就是 java 反射。
参考:

  • https://rationaleemotions.wordpress.com/2016/05/27/changing-annotation-values-at-runtime/
  • https://gist.github.com/games647/4650fde607b02215a1a4f95bca98e7ea
  • https://gist.github.com/henrrich/185503f10cbb2499a0dc75ec4c29c8f2
展开阅读全文
©️2020 CSDN 皮肤主题: 岁月 设计师: pinMode 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值