动态构造 Java 类的一种方法: javassist

http://labs.jboss.com/javassist/
这个Jboss 的项目可以动态的构造 Java 类, 其功能算是比较强大的了. 但是任何强大的东东都是双刃剑, 那就如果很好的运用, 可以大大的提升系统的灵活性, 可扩展性和性能; 如果使用不当,对系统的冲击也是很大的.

这里我不介绍具体的开发方法(可以到上面的网址去获取开发文档), 我会从其使用的场景, 系统层次等方面介绍怎样才算是很好的使用这个技术. 首先我介绍一些使用原则:

1. 动态构建 Java 类, 跟反射机制一样, 其强大, 但是不能滥用. (我先前写一了篇文章介绍反射的一个使用原则.) 动态构建 Java 类也最好跟反射机制一样只使用在模块内部, 不要跨模块调用. 比如, 模块A需要使用模块B 的一个类, 那么就将这个类在 模块 B 中生成好, 传递给模块A; 不要通过模块A 去生成 这个类.

2. 使用 动态类生成技术, 最好只针对一些简单的 java 对象, 比如 Java Bean. 最好不要通过这种技术去生成逻辑处理类.

3. 基于第二点, 其生成类所依赖的其他类最好是 JDK 自带的. 如果依赖应用本身的其他类, 最好也是简单的java对象.

4. 注意资源的释放. 我们可能会不断的生成类, 那么就需要注意, 是否需要释放这些类. 比如某个类应该是动态变化的, 在新的类生成后, 就应该将以前的那个释放掉. 确保没有内存泄露等问题.

动态构造 Java 类的一种方法: javassist (2) 收藏

http://blog.csdn.net/loveyly/archive/2007/09/21/1794927.aspx 第一部分

接下来,我来举一个例子. 我们经常使用 Java Bean 来装载业务对象数据, 但是这里有一个需求就是, 对于不同的应用场景, 可能某个业务对象所包含的属性不一样, 也就是 Java Bean 中的 Property 可能不确定, 可能增加, 也可能删除一个或者多个属性. 如果开发人员自己开发这个 Java Bean 可能是无法满足这个需求了. 这里通过javassist 来动态生成 Java Bean 对象, 就是一个比较好的方法.

这里需要强调几点: 1. 我们需要确保 ClassLoader 装载所有的动态生成类时, 也可以访问普通的途径的 Java 类; 2. 因为涉及到新的Class取代旧的Claas, 需要及时通过释放 CtClass 来确保不因为其缓存导致内存不段被无限制的使用; 3. 这里动态生成 Java Bean 主要是针对动态属性的支持, 那么这就需要应用是在这样的场景下使用此特性的: 对象属性更新不是很频繁(一般也不会). 不然就会有性能问题.

这里一般会有一个业务对象模块, 对象的生成都是在该模块内部进行的, 所有使用该模块获取的对象, 都已经是一个普通的 Java Bean 对象了.

通过这个方法, 可以让业务开发人员只关心业务对象定义, 具体的 Java 类就有系统自动生成, 既灵活又方便.

动态构造 Java 类的一种方法: javassist (3) 收藏

http://blog.csdn.net/loveyly/archive/2007/09/21/1794927.aspx 第一部分
http://blog.csdn.net/loveyly/archive/2007/09/21/1794971.aspx 第二部分
动 态构造 Java 类, 还有个作用就是性能的提升. 巧用这个方法, 会大大的提升系统的性能. 我举个例子, OGNL2.7 版本中就是用 javassist 构造对象的访问代码, 将以前涉及到大量同步操作的代码全部去掉了. 这样一来, 访问对象就是直接调用一个类的方法, 没有任何反射在里面, 性能非常好.

对于性能提升, 这里主要运用到的是将很多通过反射或者 Java Bean Property 的操作封装成一个可以直接调用的 Java 代码. 一般来说, 这个封装类会实现一个接口, 然后调用者直接调用这个接口的某个方法去访问数据对象的某个成员变量.

也就是将一个本来不知道类型的对象实例, 封装成了一个统一的访问接口实现. 这也是用好动态 Java 生成技术的一个思路. 不过一定要注意, 这个接口定义一定是某个模块内部的. 比如 OGNL , 这个接口就只会在模块内部使用.

这个思路可以运用到其他很多地方. 希望大家能多多提供应用实践. 呵呵

动态构造 Java 类的一种方法: ClassLoader 的设计 (4) 收藏

http://blog.csdn.net/loveyly/archive/2007/09/21/1794927.aspx 第一部分
http://blog.csdn.net/loveyly/archive/2007/09/21/1794971.aspx 第二部分
http://blog.csdn.net/loveyly/archive/2007/09/25/1799733.aspx 第三部分

对于ClassLoader 的设计, 可以按照如下的思路进行:
1. 首先检测缓存中是否存在该className的key(注意是存在key, 可以参考我以前的一片文章http://blog.csdn.net/loveyly/archive/2007/09/19/1791577.aspx ), 如果存在, 则直接返回;
2. 否则使用 parent ClassLoader (一般是当前线程的上下文ClassLoader)查找该类, 如果找到, 放入缓存, 返回;
3. 如果没有, 使用获取对象描述, 使用javassist动态构造类, 并使用本ClassLoader 实例装载该类, 然后返回;
4. 实现一个destroy 方法, 负责清空缓存并调用 Introspector.flushCaches() (负责清空bean的一些缓存).

当更新一个对象描述时, 需要重新使用一个 ClassLoader 实例, 并调用先前的ClassLoader的destroy方法, 让其被垃圾回收.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值