Pico、JMX、微容器以及对象的易管理性

板桥里人 https://www.jdon.com 2004/12/14(转载请保留)

  一个新概念正在暗流涌动:PicoContainer/NanoContainer(以下简称pico)这样微容器正日益受到关注和广泛应用;J2SE5.0将JMX作为JDK基本API,这些技术都表明对象的易管理性(application/object manageability)呼之欲出。

  本文试图比较Pico、JMX这两种基于组件的容器管理技术,探讨对象易管理性方面的一些实践
问题和模式。

  对象易管理性中首先是被管理的对象,也称为容器的基本模型单元,在JMX中它是Mbean;而在pico中则是普通Java对象,后者比前者更加广泛,也说明两者可结合使用。

JMX和Pico

  我们进一步看看JMX的MBean特性和pico:
  1. 在JMX中,业务对象只要继承MBean接口就能够被纳入被管理范围。这些接口包括
Standard MBean, DynamicMBean 或者 ModelMBean ,不同的MBean有不同的规则。而业务对象只要是Object,就可纳入Pico的容器管理范围,因此,pico可以做JMX最外层的套子。

  2.在JMX中,MBean只能通过MBean server访问;同样,在pico中,外界只能通过容器访问其中的Object。

  3.MBeans能向MBean Server注册,以一个唯一的字符串名,而在pico中也是如此,并且,pico不要求直接实例注册,而是推荐以Class注册,并且能够自动寻找Class需要的构造参数,可见,pico在这里增强了组件注册功能。

  4.调用Mbean的方法也很特别,只需MBean名称和方法名称组合的字符串就可以,最后通过invoke调即可; 在pico中,从容器中调用对象也是以String型的key实现调用,pico是以字符串调用对象;jmx是以字符串调用对象的方法; 两者可结合使用,关于字符串调用,pico增强容器NanoContainer甚至可以通过任何语言编制的字符串脚本都可以(smell like LOP面向语言编程?或者称为面向容器编程?).

  JMX和pico结合比较调用实例如下:

Reader script = new StringReader("" +
"import org.nanocontainer.script.groovy.NanoContainerBuilder\n" +
"import org.microcontainer.jmx.JmxDecorationDelegate\n" +
"\n" +
"builder = new NanoContainerBuilder(new JmxDecorationDelegate())\n" +
"pico = builder.container() {\n" +
" component(key:javax.management.MBeanServer, instance:javax.management.MBeanServerFactory.createMBeanServer())\n" +
" component(key:org.nanocontainer.testmodel.Wilma, class:org.nanocontainer.testmodel.WilmaImpl) {\n" +
" jmx(key:'domain:wilma=default', operations:['helloCalled'], description:'jmx description text')\n" +
" }\n" +
"}");

  script是一段Groovy脚本,这段脚本是向Pico注册一个MBeanServer,并且向MBeanServer中注册一个MBean:接口是org.nanocontainer.testmodel.Wilma;实现是org.nanocontainer.testmodel.WilmaImpl,代码如下:

public interface Wilma {
  void hello();
}

public class WilmaImpl implements Wilma {

  private boolean helloCalled;

  public boolean helloCalled() {
    return helloCalled;
  }

  public void hello() {
    helloCalled = true;
  }
}

 

NanoContainer可以运行装载这个脚本:

PicoContainer pico = buildContainer(new GroovyContainerBuilder(script, getClass().getClassLoader()), null, "SOME_SCOPE");
//从pico中获得MBeanServer,pico是最外层容器,负责管理MbeanServer和MBeans的关系。
MBeanServer mBeanServer = (MBeanServer)pico.getComponentInstance(MBeanServer.class);

//JMX以字符串可以获得对象Wilma的属性和动作
ObjectName objectName = new ObjectName("domain:wilma=default");
MBeanInfo mBeanInfo = mBeanServer.getMBeanInfo(objectName);

//pico以字符串为key实现调用对象的
Wilma wilma = (Wilma)pico.getComponentInstance(Wilma.class);
wilma.hello();//调用WilmaImpl的hello方法

//jmx以字符串实现对象方法的调用,监察上句执行结果
Boolean called = (Boolean)mBeanServer.invoke(objectName, "helloCalled", null, null);
//called结果为true,也就是WilmaImpl的属性helloCalled结果为true,因为hello方法被调用。
assertTrue(called.booleanValue());

 

  从以上看出,JMX和Pico互相结合,可以起到互相结合的强大威力,

  从上面代码中,我们可以发现,对于容器中的对象,可以有两种不同的切入角度或是关注角度,也是所谓分散关注:一个是by pico的调用,如wilma.hello();另外一种是JMX提供的另外一种角度,通过JMX提供 的这种角度,我们可以发现或跟踪对象内容的状态,如WilmaImpl的属性helloCalled结果被发现改变。

  这非常类似现代的一些手术,无需开刀(不打开人体这个容器),通过激光或探头手段监察手术效果。

  既然被监察、跟踪,那么就意味着可以被管理了,JMX提供的这种角度被认为是可以将对象纳入被管理范围。

  以上这段代码构架是Pico和JMX的一个综合体,可以说启动了一个新的Java编程架构,称为什么合适呢?微容器 microcontainer!

微容器与编程模式

  面向微容器编程目前是一种激动人心新的编程模式,总结上面这段代码,我们发现有一些面向微容器编程的规律或者称为模式。

  首先需要定义一个容器解读的配置,它是字符串的:

  一. 启动配置模式(JMX中称为MBeanForAppConfig pattern,见下面参考文录)
  目的:定义容器启动时需要装载的JavaBeans/MBeans信息。
  动机:容器启动时需要一些初始化配置,这样,容器启动可以装载这些对象。

  例如上面的Groovy脚本就是一段启动配置模式,在笔者的JdonSD 2.5框架中,是通过XML实现启动配置的,如:

<model key="userId" class ="com.jdon.controller.test.model.UserTest">
  <actionForm name="userActionForm"/>
  <handler class="com.jdon.controller.test.web.UserHandler"/>
  <service ref="mappingManagerEJB">
    <getMethod name="getUser" />
    <createMethod name="create" />
    <updateMethod name="update" />
    <deleteMethod name="delete" />
  </service>
</model>

<model key="addressId" class ="com.jdon.controller.test.model.AddressTest">
  <actionForm name="addressActionForm"/>
  <service ref="mappingManagerEJB">
    <getMethod name="getAddress" />
    <createMethod name="createAddress" />
    <updateMethod name="updateAddress" />
    <deleteMethod name="deleteAddress" />
  </service>
</model>

  二. 记录跟踪模式(JMX中称为MBeanWritesToLog pattern,见下面参考文录)
  目的:容器中的一些数据和状态需要拷贝到外部,如文件或图形输出等,以便跟踪。
  动机:Log日志记录是非常准确和常用的程序跟踪调试手段,通过Log4j等之类工具实现输出,可以对容器中状态掌握了解非常清楚。如上面代码中可以记录获得WilmaImpl的属性helloCalled结果为true,如果将其输出即可实现记录跟踪。

  二. 生命周期模式
  目的:微容器有创建和消亡时刻,因此必须处理好容器中每个对象生命周期。
  动机:生命周期是微容器的本质特征,处理好对象的生命周期,可以从设计上根本预防memory leak内存溢出或性能缓慢的基础缺陷,JMX在生命周期控制上非常深入,降低了编程复杂度。在Jdon论坛和2004年中国软件技术大会上我都反复强调生命周期的重要性,如果编程者考虑这点,说明对象在他的脑子里活起来了,而不是僵死的,这点也是全局工厂模式所不能替代的。

微容器和全局工厂模式

  对于客户端来说,微容器和工厂模式性质是一致的,客户端不在乎你是微容器和工厂模式,都是获得创建对象,但是对于服务端来说就不一样了,工厂模式可能有很多类,这些类都没有被约束或被管理的,因此移植起来很麻烦;而微容器有自己的疆界,可以实现服务端的对象约束和管理,移植方便:提起容器就走,:),如下图:

发表讨论

 

参考文献:

JMX架构的了解

JMX架构的了解 (MBean部分)

Java企业系统架构选择考量

PicoContainer解剖之一:PicoContainer是如何获得实例

Hibernate在PicoContainer中配置

国人最早开源IOC/AOP框架JdonFramework



http://www.picocontainer.org/

http://www.nanocontainer.org/

http://devresource.hp.com/drc/resources/jmxds/index.jsp

http://builds.codehaus.org/damagecontrol/public/root/PicoBook/checkout/nanocontainer-jmx.t2t

文中完整程序从http://www.nanocontainer.org/Source+Repositories下载,部分程序:mico.rar

 

更多依赖注射讨论

更多对象生命周期讨论

更多框架专题