??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲人成网站看在线播放,在线播放亚洲精品,亚洲中文无码亚洲人成影院http://www.tkk7.com/ericwang/category/5053.htmlzh-cnTue, 27 Feb 2007 13:12:31 GMTTue, 27 Feb 2007 13:12:31 GMT60在SPRING中实C务暂?/title><link>http://www.tkk7.com/ericwang/archive/2005/12/16/24299.html</link><dc:creator>Dion</dc:creator><author>Dion</author><pubDate>Fri, 16 Dec 2005 14:39:00 GMT</pubDate><guid>http://www.tkk7.com/ericwang/archive/2005/12/16/24299.html</guid><wfw:comment>http://www.tkk7.com/ericwang/comments/24299.html</wfw:comment><comments>http://www.tkk7.com/ericwang/archive/2005/12/16/24299.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/ericwang/comments/commentRss/24299.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/ericwang/services/trackbacks/24299.html</trackback:ping><description><![CDATA[<center><b><span style="font-size: 20px;">在SPRING中实C务暂?/span></b></center><br><center>作者:(x)Juergen Hoeller</center><br><center>译?<a target="_new">xMatrix</a></center><br><br><br><br><br><span style="color: Red;">版权声明QQ何获得Matrix授权的网站,转蝲时请<b>务必</b>以超链接形式标明文章原始出处和作者信息及(qing)本声?/span><br>作?Juergen Hoeller;<a target="_new">xMatrix</a><br>原文地址:<a target="_new">http://dev2dev.bea.com/pub/a/2005/07/spring_transactions.html</a><br>中文地址:<a target="_new">http://www.matrix.org.cn/resource/article/44/44054_Transaction+Spring.html</a><br>关键词:(x) Transaction Suspension Spring<br><br><b><span style="font-size: 16px;">摘要</span></b><br><br>Spring 框架是一个流行的Z轻量U控制反转容器的Java/J2EE应用框架Q尤其在数据讉K和事务管理方面的能力是众所周知的。Spring的声明性事务分? 可以应用CQ何POJO目标对象Qƈ且包含所有EJBZ容器理事务中的已声明事务。后台的事务理器支持简单的ZJDBC的事务和全功能的Z JTA的J2EE事务?br><br>q篇文章详细的讨Z(jin)Spring的事务管理特性。重Ҏ(gu)如何在用JTA作ؓ(f)后台事务{略的基上让POJO? 用Spring的声明性事务,q也昄?jin)Spring的事务服务可以无~地与J2EE服务器(如BEA WebLogic Server的事务协调器Q的事务协调器进行交互,作ؓ(f)EJB CMT传统事务分离方式的一个替代者?br><br><b><span style="font-size: 16px;">POJO的声明性事?/span></b><br><br>作ؓ(f)Spring声明性事务分L式的样例Q让我们来看一下Spring的样例应用PetClinic的中?j)服务外观中的配|:(x)<br><b>清单1Q?/b><br><pre title="pre code" class="overflow"><bean id="dataSource" <br>   class="org.springframework.jndi.JndiObjectFactoryBean"><br>     <property name="jndiName"><br>        <value>java:comp/env/jdbc/petclinic</value><br>     </property><br></bean><br><br><bean id="transactionManager" <br>   class="org.springframework.transaction.jta.JtaTransactionManager"/><br><br><bean id="clinicTarget" <br>   class="org.springframework.samples.petclinic.jdbc.JdbcClinic"><br>    <property name="dataSource"><ref bean="dataSource"/></property><br></bean><br><br><bean id="clinic" <br>   class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><br>    <property name="transactionManager"><ref bean="transactionManager"/></property><br>    <property name="target"><ref bean="clinicTarget"/></property><br>    <property name="transactionAttributes"><br>        <props><br>            <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop><br>            <prop key="store*">PROPAGATION_REQUIRED</prop><br>        </props><br>    </property><br></bean></pre><br><br>他遵循Spring的标准XMLBean定义格式。定义了(jin)Q?br>1、一个DataSource引用Q指向一个JNDI位置—在J2EE服务器管理下q将从JNDI环境中获取特定的DataSource?br>2、一个应用服务实现—这是一个POJOQ封装了(jin)业务和数据访问逻辑。在q里实现?jin)应用中的Clinic服务接口?br>3、一个应用服务的事务代理—这个代理ؓ(f)目标服务定义?jin)事务属性,匚w特定的方法名模式qؓ(f)之创建相应的事务。在实际的事务管理中Q代理指向一个PlatformTransactionManager实现?br><span style="color: Red;">注意</span>Q除?jin)显式的代理定义QSpringq支持自动代理机制和通过Commons Attributes或J2SE 5.0注解实现源程序的元数据使用。这些可选方法的讨论过?jin)本文的范围。可以参考Spring的文档来?jin)解相关l节?br><br><br>业务接口和业务实现是特定于应用的q且不需要关?j)Spring或者Spring的事务管理。普通Java对象可以作ؓ(f)服务的目标对象,而且M普通Java接口可以作ؓ(f)服务的接口。下面是一个Clinic接口的示例:(x)<br><b>清单2Q?/b><br><pre title="pre code" class="overflow">public interface Clinic {<br>    Pet loadPet(int id);<br>    void storePet(Pet pet);<br>    ...<br>}</pre><br><br><br>q个接口的实现如下显C,假设他用JDBC来执行必要的数据讉K。他通过bean属性的讄Ҏ(gu)来获取JDBC的DataSource;q与上面的配|中的dataSource属性定义相对应?br><b>清单3Q?/b><br><pre title="pre code" class="overflow">public class JdbcClinic implements Clinic {<br><br>    private DataSource dataSource;<br><br>    public void setDataSource(DataSource dataSource) {<br>      this.dataSource = dataSource;<br>    }<br><br>    public Pet loadPet(int id) {<br>      try {<br>          Connection con = this.dataSource.getConnection();<br>          ...<br>      }<br>      catch (SQLException ex) {<br>        ...<br>      }<br>    }<br><br>    public void storePet(Pet pet) {<br>      try {<br>          Connection con = this.dataSource.getConnection();<br>          ...<br>      }<br>      catch (SQLException ex) {<br>        ...<br>      }<br>    }<br><br>    ...<br>}</pre><br><br> <br>如你所见,代码相当直接。我们用一个简单的Java对象Q而事务管理由事务代理来处理,q个我们?x)在下面讨论?br>注意在PetClinicCZ应用中实际的ZJDBC的Clinic实现利用?jin)Spring的JDBC支持cL避免直接使用JDBC的API。虽然Spring的事务管理也可以与普通的ZJDBC实现一起工作,向上面的示例?br><br><b>定义事务代理</b><br>除了(jin)JdbcClinic实例以外Q配|中也定义了(jin)一个事务代理。如果愿意这个代理所暴露的实际接口也可以昑ּ定义。默认情况下Q所有由目标对象实现的接口都暴露出来Q在q个例子中就是应用的Clinic服务接口?br><br>从客L(fng)的观Ҏ(gu)看,"clinic" bean只是q个应用的Clinic接口的实现。客L(fng)不需要知道这?x)被一个事务代理所处理。这是接口的能力:(x)一个直接的目标对象的引用可以容易的被一个实现相同接口的代理所代替—在q儿是一个隐式创Z务的代理?br>代理的具体事务行Z(x)׃ؓ(f)Ҏ(gu)特定的方法或Ҏ(gu)命名模式而定义的事务属性来驱动Q就像下面的例子所C:(x)<br><b>清单3Q?/b><br><pre title="pre code" class="overflow"><prop key="load*">PROPAGATION_REQUIRED,readOnly</prop><br><prop key="store*">PROPAGATION_REQUIRED</prop></pre><br><br>Key属性决定代理将为方法提供什么样的事务行为。这个属性的最重要部分是事务传播行ؓ(f)。下面是一些可选的属性|(x)<br>1、PROPAGATION_REQUIRED --支持当前的事务,如果不存在就创徏一个新的。这是最常用的选择?br>2、PROPAGATION_SUPPORTS --支持当前的事务,如果不存在就不用事务?br>3、PROPAGATION_MANDATORY --支持当前的事务,如果不存在就抛出异常?br>4、PROPAGATION_REQUIRES_NEW --创徏一个新的事务,q暂停当前的事务Q如果存在)(j)?br>5、PROPAGATION_NOT_SUPPORTED --不用事务,q暂停当前的事务Q如果存在)(j)?br>6、PROPAGATION_NEVER --不用事务,如果当前存在事务抛出异常?br>7、PROPAGATION_NESTED --如果当前存在事务׃为嵌入事务执行,否则与PROPAGATION_REQUIREDcM?br><br>? 个事务策略与EJB的CMTcMQ而且使用相同的常量名Q因此对EJB开发h员来说是很亲切的。第7个策略PROPAGATION_NESTED? Spring提供的一个变体:(x)他需要事务管理器(如DataSourceTransactionManager)提供cMJDBC3.0那样的保存点 API来嵌套事务行为或者通过<br>JTA支持嵌套事务?br><br>事务属性中的readOnly标识指示相应的事务应该作Z个只M务来优化。这是一个优化提C:(x)一些事务策略在q种情况下可以得到很好的性能优化Q如使用ORM工具如Hibernate或TopLink旉免脏数据(g)查(“flush”尝试)(j)?br><br>在事务属性中q有一个“timeout”选项来定义事务的时U数。在JTA中,q个属性会(x)单地传递给J2EE服务器的事务协调器ƈ被正地解释?br><br><b>使用事务代理</b><br>? q行Ӟ客户端会(x)取得一个“clinic”引用ƈ转换为Clinic接口Q然后调用如loadPet或storePetҎ(gu)。这隐式地使用? Spring的事务代理,通过“事务解释器”在目标对象中注册;q样一个新的事务就创徏?jin),然后具体的工作就会(x)代理给JdbcClinic的目标方法?br>?CZ?jin)一个用“徏议链”ƈ到达最后目标的AOP代理的潜在概c(din)在q个CZ中,唯一的徏议是一个事务解释器用来包装目标Ҏ(gu)的事务行为。这是一U用来在声明性事务功能下使用的基于代理的AOP?br> <br><br><img src="http://www.matrix.org.cn/resource/upload/forum/2005_12_16_002248_zxcVMhvTna.gif" alt="" style="display: inline;" onmouseover="javascript:ImgShowTip(this);" onload="javascript:ImgLoad(this);" onclick="javascript:ImgClick(this);" border="0"><br>Figure 1. An AOP proxy with an advisor chain and a target at the end<br><br>例如Q一个PetClinic应用的WEB层组件可以执行ServletContext定位来获取Spring WebApplicationContext的引用ƈ且获取受理的“clinic”BEANQ?br><b>清单4Q?/b><br><pre title="pre code" class="overflow">WebApplicationContext ctx = <br>   WebApplicationContexUtils.getWebApplicationContext(servletContext);<br>Clinic clinic = (Clinic) ctx.getBean("clinic);<br><br>Pet pet = new Pet();<br>pet.setName("my new cat");<br><br>clinic.storePet(pet);</pre><br><br>? 调用storePet()之前QSpring的事务代理隐式地创徏一个事务。当storePet()调用q回Ӟ事务提交或回滚。缺省情况下M RuntimeException或Error导致回滚。实际的提交或回滚可以是可以定义的:(x)Spring的事务属性支持“回滚规则”的概念?br><br>例如Q我们可以可以引入一个强制的PetClinicExceptionq且告诉事务代理在抛出异常时回滚Q?br><b>清单5Q?/b><br><pre title="pre code" class="overflow"><prop key="load*">PROPAGATION_REQUIRED,readOnly,-PetClinicException</prop><br><prop key="store*">PROPAGATION_REQUIRED,-PetClinicException</prop></pre><br><br>q儿也有一个类似的“提交规则”语法,指示特定的异常将触发一ơ提交?br>? 意上面示例的昑ּ定位引用的方法只是一U访问受Spring理BEAN的方法的变化Q可以用在Q何WEB资源如servlet或filter。在构徏? 于Spring自n的MVC框架ӞBEAN可以直接被注到WEB控制器中。当然也支持在如Struts, WebWork, JSF, and Tapestry框架中访问Spring理BEAN。详情可以参考Spring的文档?br><br><b><span style="font-size: 16px;">PlatformTransactionManager{略</span></b><br><br>Spring 事务支持的核?j)接口是org.springframework.transaction.PlatformTransactionManager。所? Spring的事务分d能都?x)委托给PlatformTransactionManagerQ传l相应的TransactionDefinition? 例)(j)来做实际的事务执行。虽然PlatformTransactionManager接口可以直接调用Q但通常应用只需要配|一个具体的事务理器ƈ且? q声明性事务来分离事务?br><br>Spring提供几种不同的PlatformTransactionManager实现Q分为如下两个类别:(x)<br>1? 本地事务{略—支持单一资源的事务(通常是单个数据库Q,其包? org.springframework.jdbc.datasource.DataSourceTransactionManager? org.springframework.orm.hibernate.HibernateTransactionManager?br>2、全局事务理—支持可能跨多个资源的全局事务。其相应的类为org.springframework.transaction.jta.JtaTransactionManagerQ将事务委托l遵循JTA规范的事务协调器Q通常为J2EE服务器,但不是强制的Q?br><br>PlatformTransactionManager 抽象的主要h(hun)值在于应用不再被l定在特定的事务理环境。相反,事务{略可以很容易地切换—通过选择不同? PlatformTransactionManager实现cR这׃得应用代码与声明事务分离保持一_(d)而不需要考虑应用lg所使用的环境了(jin)?br><br>? 如,应用的初始版本可能布|在Tomcat上,与单个Oracle数据库交互。这可以方便地利用Spring的事务分ȝ性,只要选择ZJDBC? DataSourceTransactionManager作ؓ(f)使用的事务策略。Spring?x)分M务,而JDBC驱动?x)执行相应的原始JDBC事务?br><br>? 同应用的另一个版本可能会(x)布v在WebLogic服务器上Q用两个Oracle数据库。应用代码和事务分离不需要改变。唯一不同的是选择作ؓ(f) JtaTransactionManager事务{略Q让Spring来分M务而W(xu)ebLogic服务器的事务协调器来执行事务?br><br><b>JTA UserTransaction与JTA TransactionManager比较</b><br>让我们来看一下Spring对JTA支持的细节。虽然ƈ非经帔R要考虑q个l节但了(jin)解相关的l节q有必要的。对单的用例如前面章节的CZQ标准的JtaTransactionManager定义已经_?jin)?br>~? 省的Spring JtaTransactionManager讄?x)从标准JNDI位置QJ2EE规范所定义的java:comp/UserTransactionQ获? JTA的javax.transaction.UserTransaction对象。这对大部分标准J2EE环境来说已经_?jin)?br><br>然而, ~省的JtaTransactionManager不能执行事务暂停Q也是说不支持PROPAGATION_REQUIRES_NEW? PROPAGATION_NOT_SUPPORTEDQ。原因就在于标准的JTA UserTransaction接口不支持事务的暂停和恢复,而只支持开始和完成新的事务?br><br>Z(jin)实现事务的暂停,需要一? javax.transaction.TransactionManager实例Q他提供?jin)JTA定义的标准的暂停和恢复方法。不q的是,J2EE没有? JTA TransactionManager定义标准的JNDI位置Q因此,我们需要用厂商自q定位机制?br><b>清单6Q?/b><br><pre title="pre code" class="overflow"><bean id="transactionManager" <br>   class="org.springframework.transaction.jta.JtaTransactionManager"><br>     <property name="transactionManagerName"><br>        <value>vendorSpecificJndiLocation</value><br>     </property><br></bean></pre><br><br><br>J2EE 本质上没有考虑JTA TransactionManager接口作ؓ(f)公共API的一部分。JTA规范自n定义?jin)将TransactionManager接口作ؓ(f)容器集成的想 法。虽然这是可以理解的Q但是JTA TransactionManager的标准JNDI位置q是可以增加一定的价|特别是对轻量U容器如Spring,q样MJ2EE服务器就可以用统 一的方式来定位JTA TransactionManager?jin)?br><br>不仅Spring的JtaTransactionManager可以? 讉K中获益,O/R映射工具如Hibernate, Apache OJB, and Kodo JDO也能得到好处Q因Z们需要在JTA环境中执行缓存同步的能力Q释攄存意味着JTA事务的完成)(j)。这U注册事务同步的能力只有JTA TransactionManager接口才能提供Q而UserTransaction是处理不?jin)的。因此,q些工具都需要实现自q TransactionManager定位器?br><br>为JTA TransactionManager定义标准的JNDI位置是许多底层Y件供应商最期望J2EE实现的功能。如果J2EE5.0的规范制定团队能够认? 到这个特性的重要性就太好?jin)。幸q地是,高J2EE服务器如WebLogic Server已经考虑JTA TransactionManager作ؓ(f)公共的API包含在扩展功能中?br><br><span style="font-size: 16px;"><b>在WebLogic JTA中实现Spring的事务分?/b></span><br>在WebLogic Server中,JTA TransactionManager官方的JNDI位置定义为javax.transaction.TransactionManager。这个值可? 在Spring的JtaTransactionManager中作为“transactionManagerName”用。原则上q样可以在 WebLogic's JTApȝ中实C务暂停了(jin)Q也是说支持PROPAGATION_REQUIRES_NEW和PROPAGATION_NOT_SUPPORTED? 为?br><br>除了(jin)标准的JtaTransactionManager和其支持的通用配置选项外,Springq提供了(jin)一个专用的WebLogicJtaTransactionManager适配器来直接利用WebLogic的JTA扩展?br><br>在n受自动探WebLogic的JTA TransactionManager的便利之外,他提供超标准JTA的三个重要特性:(x)<br>1、事务命名—暴露出Spring的事务名lWebLogic ServerQ得Spring事务在WebLogic的事务监听器可见。缺省的QSpring?x)用声明性事务的完整Ҏ(gu)名?br>2、每事务隔离U别—将Spring事务属性中定义的隔ȝ别应用到WebLogic JTA事务中。这使得每个事务都可以定义数据库的隔ȝ别,而这是标准JTA所不支持的?br>3、强制事务恢复—即使在暂停的事务被标识为回滚时也可以恢复。这需要用WebLogic的扩展TransactionManager接口来调用forceResume()Ҏ(gu)?br> <br><img src="http://www.matrix.org.cn/resource/upload/forum/2005_12_16_002258_JYlbkfxrnW.gif" alt="image" style="display: inline;" onmouseover="javascript:ImgShowTip(this);" onload="javascript:ImgLoad(this);" onclick="javascript:ImgClick(this);" border="0" width="600"><br>Figure 2. WebLogic Server's transaction monitor (click the image for a full-size screen shot)<br><br>Spring的WebLogicJtaTransactionManager有效Cؓ(f)ZSpring的应用提供了(jin)WebLogic Server事务理的全部功能。这使得Spring事务分离成ؓ(f)一U能与EJB CMT竟争的品,而且提供?jin)相同别的事务支持?br><br><b><span style="font-size: 16px;">Spring and EJB CMT</span></b><br><br>? 上所C,Spring的POJO声明性事务分d以作ZU除传统EJB CMTq外的选择。但是Spring与EJBq不是完成互斥的QSpring的应用上下文也可以作为EJB fa&ccedil;ade的后台来理数据讉KQDAOQ和其他l纹理的业务对象?br><br>在EJB情景中,事务是由EJB CMT来驱动的。对Spring来说Q数据访问支持特性会(x)自动(g)到q样的环境ƈ且采用相应的事务。例如,Spring对Hibernate的支持能够提 供隐式的资源理Q即使是EJB驱动的事务,甚至可以在不需要修改Q何DAO代码的情况下提供相同的语义?br>Spring有效的解耦了(jin)DAO实现与实际的q行环境。DAO可以参与Spring的事务就像参与EJB CMT事务一栗这不仅化在其他环境中的重用Q而且更方便在J2EE容器外进行测试?br><br><b><span style="font-size: 16px;">l论</span></b><br>Spring框架为J2EE和非J2EE环境提供?jin)全量的事务分离的特性,特别表现在POJO的声明性事务上。他用一U灵z而非侵入式的方式为非EJB环境中的事务分离提供?jin)便利。与EJB不同Q这L(fng)事务性POJO应用对象可以很容易的被测试和在J2EE容器外补重用?br><br>Spring 提供?jin)各U事务策略,如JtaTransactionManager是用来代理J2EE服务器的事务协调器,而JDBC DataSourceTransactionManager是用来ؓ(f)单的JDBC DataSourceQ就是单一目标数据库)(j)执行事务。Spring可以很容易ؓ(f)不同的环境通过后台配置的简单修Ҏ(gu)调整事务{略?br><br>越 标准的JTA支持QSpring为WebLogic Server的JTA扩展提供?jin)完善的集成Q可以支持高U特性如事务监视和每事务隔离U别。通过对WebLogic Server的特D支持,ZSpring的应用可以完全利用WebLogic Server的事务管理功能?br><br>Spring事务分离是 EJB CMT之外的另一U可选方式,特别是对那些ZPOJO的轻量架构。在那只是因为选择LSSBQ本地无状态会(x)话BEANQ来应用声明性事务的情况下,? 于Spring的POJO服务模型是一U可行的选择Q他提供?jin)非帔R层的灉|性、可试性和重用性?br><br><b><span style="font-size: 16px;">资源</span></b><br>&#8226;<a target="_new">JTA - The JTA specification JTA规范</a><br>&#8226;<a target="_new">WebLogic JTA - Documentation of WebLogic's JTA extensions WebLogic  JTA扩展文档</a><br><br><b><span style="font-size: 16px;">关于作?/span></b><br>Juergen Hoeller是Spring框架的创始h之一<img src ="http://www.tkk7.com/ericwang/aggbug/24299.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/ericwang/" target="_blank">Dion</a> 2005-12-16 22:39 <a href="http://www.tkk7.com/ericwang/archive/2005/12/16/24299.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【{载】Spring中用Annotation同时标记JMS+数据库事?/title><link>http://www.tkk7.com/ericwang/archive/2005/12/13/23751.html</link><dc:creator>Dion</dc:creator><author>Dion</author><pubDate>Tue, 13 Dec 2005 15:49:00 GMT</pubDate><guid>http://www.tkk7.com/ericwang/archive/2005/12/13/23751.html</guid><wfw:comment>http://www.tkk7.com/ericwang/comments/23751.html</wfw:comment><comments>http://www.tkk7.com/ericwang/archive/2005/12/13/23751.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/ericwang/comments/commentRss/23751.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/ericwang/services/trackbacks/23751.html</trackback:ping><description><![CDATA[<div id="1111161" class="postTitle"> <a id="viewpost1_TitleUrl" class="postTitle2" >[java]Spring中用Annotation同时标记JMS+数据库事?/a> </div> <p>对spring ?jin)解的不够精通,q两天在解决jms异常的过E中发现Qspring中提供了(jin)jmsTrasactionManagerQ同样实C(jin)事务理接口。这L(fng) 自动的拦截器Q就可以象数据库一栯动控制事务。在同时配置?jin)JMS和数据库事务的时候,两者同时有效。这L(fng)l的消息和数据库事务p量的一致了(jin)Q?br><br>数据库的spring配置参见Q?a >http://steeven.cnblogs.com/archive/2005/06/14/174410.html</a><br>jms部分如下Q?br></p> <div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">bean </span><span style="color: rgb(255, 0, 0);">id</span><span style="color: rgb(0, 0, 255);">="remoteJmsConnectionFactory"</span><span style="color: rgb(255, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        class</span><span style="color: rgb(0, 0, 255);">="org.activemq.ActiveMQConnectionFactory"</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="useEmbeddedBroker"</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">            </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">value</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);">true</span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">value</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">property</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="brokerURL"</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">            </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">value</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);">tcp://localhost:61616</span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">value</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">property</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">    </span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">bean</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">    </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">bean </span><span style="color: rgb(255, 0, 0);">id</span><span style="color: rgb(0, 0, 255);">="jmsTM"</span><span style="color: rgb(255, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        class</span><span style="color: rgb(0, 0, 255);">="org.springframework.jms.connection.JmsTransactionManager"</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="connectionFactory"</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">            </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">ref </span><span style="color: rgb(255, 0, 0);">bean</span><span style="color: rgb(0, 0, 255);">="remoteJmsConnectionFactory"</span><span style="color: rgb(255, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">/></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">property</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">    </span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">bean</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">    </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">bean </span><span style="color: rgb(255, 0, 0);">id</span><span style="color: rgb(0, 0, 255);">="jmsTransactionInterceptor"</span><span style="color: rgb(255, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        class</span><span style="color: rgb(0, 0, 255);">="org.springframework.transaction.interceptor.TransactionInterceptor"</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="transactionManager"</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">            </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">ref </span><span style="color: rgb(255, 0, 0);">bean</span><span style="color: rgb(0, 0, 255);">="jmsTM"</span><span style="color: rgb(255, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">/></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">property</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="transactionAttributeSource"</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">            </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">bean<br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">                </span><span style="color: rgb(255, 0, 0);">class</span><span style="color: rgb(0, 0, 255);">="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"</span><span style="color: rgb(255, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">/></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">property</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">    </span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">bean</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">    </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">bean<br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(255, 0, 0);">class</span><span style="color: rgb(0, 0, 255);">="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor"</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="transactionInterceptor"</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">            </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">ref </span><span style="color: rgb(255, 0, 0);">bean</span><span style="color: rgb(0, 0, 255);">="jmsTransactionInterceptor"</span><span style="color: rgb(255, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">/></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">property</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">    </span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">bean</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">    </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">bean </span><span style="color: rgb(255, 0, 0);">id</span><span style="color: rgb(0, 0, 255);">="destResolver"</span><span style="color: rgb(255, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        class</span><span style="color: rgb(0, 0, 255);">="test.message.EnumDestinationResolver"</span><span style="color: rgb(255, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">/></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">    </span><span style="color: rgb(0, 128, 0);"><!--</span><span style="color: rgb(0, 128, 0);"> for send jms to remote server </span><span style="color: rgb(0, 128, 0);">--></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">    </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">bean </span><span style="color: rgb(255, 0, 0);">id</span><span style="color: rgb(0, 0, 255);">="remoteJmsTemplate"</span><span style="color: rgb(255, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        class</span><span style="color: rgb(0, 0, 255);">="org.springframework.jms.core.JmsTemplate"</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="connectionFactory"</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">            </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">ref </span><span style="color: rgb(255, 0, 0);">bean</span><span style="color: rgb(0, 0, 255);">="remoteJmsConnectionFactory"</span><span style="color: rgb(255, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">/></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">property</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="destinationResolver"</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">            </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">ref </span><span style="color: rgb(255, 0, 0);">local</span><span style="color: rgb(0, 0, 255);">="destResolver"</span><span style="color: rgb(255, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">/></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">        </span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">property</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">    </span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">bean</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span></div><br>应用E序很简?br><span style="color: rgb(0, 0, 0);">@Transactional<br><img id="Codehighlighter1_67_282_Open_Image" onclick="this.style.display='none'; Codehighlighter1_67_282_Open_Text.style.display='none'; Codehighlighter1_67_282_Closed_Image.style.display='inline'; Codehighlighter1_67_282_Closed_Text.style.display='inline';" src="http://steeven.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_67_282_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_67_282_Closed_Text.style.display='none'; Codehighlighter1_67_282_Open_Image.style.display='inline'; Codehighlighter1_67_282_Open_Text.style.display='inline';" src="http://steeven.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> TestServiceImpl implements TestService </span><span id="Codehighlighter1_67_282_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://steeven.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_67_282_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img id="Codehighlighter1_101_280_Open_Image" onclick="this.style.display='none'; Codehighlighter1_101_280_Open_Text.style.display='none'; Codehighlighter1_101_280_Closed_Image.style.display='inline'; Codehighlighter1_101_280_Closed_Text.style.display='inline';" src="http://steeven.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_101_280_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_101_280_Closed_Text.style.display='none'; Codehighlighter1_101_280_Open_Image.style.display='inline'; Codehighlighter1_101_280_Open_Text.style.display='inline';" src="http://steeven.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> someMethod() </span><span id="Codehighlighter1_101_280_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://steeven.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_101_280_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">        getJmsTemplate().send(someMessage);<br></span><span style="color: rgb(0, 0, 0);"><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">    }</span></span><span style="color: rgb(0, 0, 0);"><br><img src="http://steeven.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}<br></span></span><img src ="http://www.tkk7.com/ericwang/aggbug/23751.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/ericwang/" target="_blank">Dion</a> 2005-12-13 23:49 <a href="http://www.tkk7.com/ericwang/archive/2005/12/13/23751.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【{载】hibernate3.0+ejb3 annotaion配置实战+spring1.21 annotation事务控制http://www.tkk7.com/ericwang/archive/2005/12/13/23747.htmlDionDionTue, 13 Dec 2005 15:32:00 GMThttp://www.tkk7.com/ericwang/archive/2005/12/13/23747.htmlhttp://www.tkk7.com/ericwang/comments/23747.htmlhttp://www.tkk7.com/ericwang/archive/2005/12/13/23747.html#Feedback2http://www.tkk7.com/ericwang/comments/commentRss/23747.htmlhttp://www.tkk7.com/ericwang/services/trackbacks/23747.html阅读全文

Dion 2005-12-13 23:32 发表评论
]]>
扩展 Spring ?JMX 支持http://www.tkk7.com/ericwang/archive/2005/12/09/23230.htmlDionDionFri, 09 Dec 2005 15:23:00 GMThttp://www.tkk7.com/ericwang/archive/2005/12/09/23230.htmlhttp://www.tkk7.com/ericwang/comments/23230.htmlhttp://www.tkk7.com/ericwang/archive/2005/12/09/23230.html#Feedback0http://www.tkk7.com/ericwang/comments/commentRss/23230.htmlhttp://www.tkk7.com/ericwang/services/trackbacks/23230.html

扩展 Spring ?JMX 支持

?Spring 框架定制资源理

developerWorks
文档选项
此作为电(sh)子邮件发? height=

此作为电(sh)子邮件发?/b>

未显C需?JavaScript 的文档选项

讨论

样例代码


Ҏ(gu)늚评h(hun)

帮助我们改进q些内容


U别: 中

Claude Duguay , 高 J2EE 架构? Capital Stream Inc.

2005 q? 11 ? 24 ?/p>

Spring 框架体pȝ构依赖性降x低,q且应用程序中的组成部分进行了(jin)具体化,但是应用E序仍然是需要管理的。幸q的是,Spring 1.2 包括高? JMX 集成支持Qƈ?JMX 为应用程序提供了(jin)一U实用的理基础架构。在本文中,Claude Duguay ?Spring JMX 更进一步,向?zhn)展示了(jin)如何?f)Ҏ(gu)和属性透明地增加通知事g。最后得到的代码使?zhn)可以监视状态变化,同时不会(x)搞ؕ Java?对象?/blockquote>

? ?Spring 框架?JMX 理基础架构的默认配|已l很不错?jin),但是仍然有定制的余地Q特别是涉及(qing) Model MBean 提供的更高层功能时。在本文中,我用了(jin)一U相对简单的操作 —?为基?Spring 的应用程序的Ҏ(gu)和属性增加通知事g —?以帮助?zhn)熟(zhn)? Spring JMX 的定制。从头到֮成我的例子后Q?zhn)可以根据自己应用程序的需要调?Spring JMX 理基础架构?/p>

我首 先对 JMX API、Spring 框架?Spring JMX q行单回,然后转入开发扩展。第一个扩展让我可以用一个外?XML 格式配置 MBean 元数据,q个格式Q像 Hibernate 映射文gQ可以与 Java 对象一起存储在c\径中。我的第二个扩展?ModelMBean cd加一个简单的命名规范Q以透明地配|定制的通知消息。在属性改变时或者调用了(jin)特定的方法之前或者之后触发新的通知消息?/p>

文章的最后是一个基?mockup 服务对象的实际例子,需要管理它的启动和停止Ҏ(gu)和读写属性。我用一个专门ؓ(f)此设计的型客户?服务器应用程序测试了(jin)q个实现。应用服务器是一个标?Java 5.0 MBeanServerQƈ补充?jin)源?MX4J 开放源码项目的 HTTP 适配器。关于文章源代码请参?下蝲Q而技术下载请参阅 参考资?/a>?/p>

JMX 概述

Java Management ExtensionsQJMXQ是理和监视网l上的服务的、基?Java 的标准。JMX API 的核?j)是受?beanQ即 MBean。MBean 为受资源(如应用程序、服务和讑֤Q提供了(jin)设施层。简而言之,MBean 提供?jin)一U灵zȝ、基于适配器的体系l构Q用于开攑֟?Java 的(或?Java 包装的)(j)资源的属性和操作。开攑֐Q就可以用浏览器?HTTP q接或者通过?SMTP 或?SOAP q样的协议监视和理q些资源?/p>

~写和部|的 MBean 是通过 MBeanServer 接口开攄Q以使不同的应用E序视图h交互性?code>MBeanServer 实例q可以结合到L的联合关pMQ构成更复杂的分布式环境?/p>

JMX 标准提供?jin)四U不同的 MBeanQ?/p>

  • Standard MBean 直接实现用于理对象的方法,既可以通过实现一个由E序员定义的、类名以 ?code>MBean?l束的接口,也可以用一个以一个类作ؓ(f)构造函数参数的 Standard MBean 实例Q加上一个可选的接口c规范。这个接口可以开攄于管理的部分对象Ҏ(gu)?br>
  • Dynamic MBean 用属性访问器动态地讉K属性,q用一个一般化?invoke() Ҏ(gu)调用Ҏ(gu)。可用的Ҏ(gu)是在 MBeanInfo 接口中指定的。这U方式更灉|Q但是不h?Standard MBean 那样的类型安全性。它极大地降低了(jin)耦合性,可管理的 POJOQ纯_的老式 Java 对象Q不需要实现特定的接口?br>
  • Model MBean 提供?jin)一个改q的抽象层,q扩展了(jin) Dynamic MBean 模型以进一步减对l定实现的依赖性。这对于可能使用多个版本?JVM 或者需要用松散耦合理W三方类的情况会(x)有帮助。Dynamic MBean ?Model MBean 之间的主要区别是Q在 Model MBean 中有额外的元数据?br>
  • Open MBean 是受限的 Model MBeanQ它限制cd为固定的一l类型,以得到最大的可移植性。通过限制数据cdQ可以用更多的适配器,q且?SMTP q样的技术可以更Ҏ(gu)适应 Java 应用E序的管理。这U变体还指定?jin)数l和表等标准l构以改q复合对象的理?/li>

? 果要同时控制客户机和服务器,那么 Standard MBean 是最Ҏ(gu)实现的一U变体。它们的优点是有cdQ但是如果在更一般化的管理控制台环境中用时?x)缺一些灵zL。如果计划?Dynamic MBeanQ那么?zhn)也可以更一步?Model MBeanQ在大多数情况下它会(x)改善抽象层而几乎不?x)增加复杂性。Open MBean 是是可移植性最高的一U变体,如果需要开攑֤合对象,那么它是惟一的方法。不q的是,?Open MBean 中开攑֤合结构所需要的代码数量q多Q只有在需要高U的商业理解决Ҏ(gu)时才合算?/p>

JMX q支持用带qo(h)器和q播器的事g模型的通知。ؓ(f)此目的,Standard MBean 需要声明一?MBeanInfo 元数据描q? Standard MBean 实现通常在内部构造这些内容,开发h员不能直接看到它们。在本文后面Q?zhn)会(x)看到如何?Model MBean 元数据的 XML 描述W格式和 Spring ?JMX 支持q行实际上透明的配|?/p>

回页?/b>


Spring 提供帮助

? J2EE 一PSpring 框架在一个体pȝ构中提供?jin)许多强大?Java 开发功能。与 J2EE 不同的是QSpring 开攑֞的技术来源提供了(jin)范围q泛的选择Q不再有依赖性的负担。例如,Spring 的对象关pL工具可以复?Enterprise JavaBean 的行为,同时不会(x)D不灵zR虽? EJB 规范限制?jin)这U方式,但是 Spring 提供?jin)大量技术接口,使?zhn)可以选择最适合应用E序要求的接口,或者在需要时创徏自己的接口。与此类|利用 Spring 的动态代理类?Java 对象增加事务性或者安全限Ӟ使它们保持整zƈ针对应用E序I间而不是基架构要求?/p>

Spring 的支?AOP 的、以复合Z?j)的QIOCQbean 可以很大E度上基础架构和业务对象彼此分R因此,横切x点(如日志、事务和安全Q不?x)再q扰应用E序代码?/p>

IOC Q控制反转)(j)是减耦合度的主要{略。Spring ?IOC 实现使用依赖性注入有效地控制从应用E序代码 “反转”到 Spring 容器。Spring 不是在创建时类耦合到应用程序的对象图,它(zhn)可以用 XML 或者属性文Ӟ管 XML 被认为是最好的Ҏ(gu)Q配|类?qing)它们的依赖性。然后用标准讉K器将引用“注入”到cL依赖的对象中。可以将它看成具体化复合Qexternalizing compositionQ,在典型应用程序中Q它的比重远q大于ѝ?/p>

AOP 是在应用E序开发中理横切x点的关键。就像在传统面向对象~程中实现的那样Q这些关注点是作为单独的实例处理的,有可能在应用E序cM产生互不相关的代码(是混ؕQ? Spring 使用 AOP 规范和一?XML 配置文g具体化横切关注点Q因而保持了(jin) Java 代码的纯z性?/p>

回页?/b>


介绍 Spring JMX

Spring 1.2 中的 JMX 支持使用Ҏ(gu)配置?bean 代理提供?jin)自?MBeanServer 注册Qƈ支持标准 JSR-160 q程q接器。在最单的情况下,可以?Spring JMX ?MBeanExporter cL册对象。Spring 自动识别 StandardMBean 或者用 ModelMBean 代理包装对象Q在默认情况下用内省。可以以昑ּ引用使用 BeanExporter 以声?beanQ或者可以用默认{略或更复杂的策略自动检?bean?/p>

Spring 1.2 提供的大量装配器使得透明地构?MBean 成ؓ(f)可能Q包括用内省、Standard MBean 接口、元数据Q用类U别注释Q和昑ּ声明的方法名。Spring 的基于导出器和装配器的模型容易扩展,q在创徏注册?MBean 时提供所需要的控制能力?/p>

JMX 使用 ObjectName 语言注册和访问管理对象。如果选择使用自动注册Q那?Spring 提供?jin)不同的命名{略。用“键”命名策略时Q可以用一个属性把 MBean 名与 NameObject 实例兌h。如果实? ManagedResource 接口Q那么可以用元数据命名规范。由?Spring 高度灉|的体pȝ构和大量扩展点,q可以实现自已的{略?/p>

在默认情况下QSpring ?x)发现运行?MBeanServer 实例Q如果没有实例在q行或者没有显式声明的话,它会(x)创徏一个默认实例。用 Spring 配置直接实例化自q MBeanServer 与用各U连接器同样Ҏ(gu)。Spring 通过客户机和服务器连接提供控Ӟq提供客h代理以协助客L(fng)~程?/p>

所 有这些功能都?Spring 1.2 默认提供的。虽?Spring JMX 提供?jin)大量选项Q但是默认的导出器对于许多项目来说已l够了(jin)Q(zhn)可以很快地投入q行。不q,使用 JMX Ӟ在用隐?MBean 构造时?x)注意到一些特性。结果,可能?x)慢慢地?Standard MBean 转移?Model MBeanQ它允许对应用程序的属性、操作和通知元数据施加更多的控制。要保留松散耦合的好处(也就?Spring 灉|的体pȝ构内在的优点Q,需要在 Java 对象之外实现q个控制?/p>

Spring ?IOC 使得从外部连接(wireQ对象依赖性容易了(jin)Q在 Spring 的体pȝ构中很容易利用这U优炏VIOC 保持对象依赖性的可注入性,q得增加、替换或者补充对象的行ؓ(f)Q包?Spring ?JMX 支持Q变得轻而易举。在本文的其余部分,我将重点攑ֈ扩展 Spring JMX 以得到更l化的应用程序管理,而不?x)搞乱应用程序代码或者破? Spring 固有的灵zL?/p>

回页?/b>


扩展 Spring JMX

Spring 框架提供?jin)许多处?JMX 的有用工P包括用于扩展 JMX 功能的扩展点。我利用它们获得对 MBeanInfo 声明的更多控Ӟ同时不用?Java 对象施加注释。ؓ(f)此,我将要以两种方式扩展 Spring JMXQ第一U方法可以用一个外?XML 格式Q类g JBoss 微内核)(j)配置 MBean 元数据,W二U方法可以与其相兌?Java 对象一同存储在在类路径中(很像 Hibernate 映射文gQ?/p>
推荐的文?/b>

Spring 1.2 的文档有整整一章关?JMX 的内容,如果惌?Spring 中?JMX 应该阅d。有?Spring 1.2 文档的内容请参阅 参考资?/a>?/p>

我将扩展 RequiredModelMBean c,让它使用一个简单的命名规范Q以 <ClassName>.mbean.xml 格式L相关?MBean 部v描述W。定义这U基?XML ?MBean 描述W改q了(jin)对应用程序元数据的控Ӟ而不?x)失d?POJO 的设计和 Spring 复合的灵zL。ؓ(f)?jin)实现这一点,我将实现自己的装配器q扩展基本的 Spring JMX 导出器。扩展的导出器可以创建扩展的 ModelMBeanQ它支持截获属性的改变以及(qing) before ?after Ҏ(gu)执行的通知。我可以?Spring ?AOP 机制完成q一切,但是 ModelMBean 已经是底层受资源的代理Q因此我用更直接的方式扩展 RequiredModelMbean cR?/p>

理基础

不管使用什么技术,在管理资源时有三个要x的主要领域:(x)

  • 属性(attributeQ?/b> Q有时称为属性(propertyQ、字D|者变量)(j)。只d性对于开攑ֺ量或者状态很有用。读/写属性ɽ理员可以改变配|?br>
  • 动作QactionQ?/b> Q可执行调用Q对?Java 代码来说是Ҏ(gu)Q。动作用于触发像启动和关闭这L(fng)事gQ或者其他特定于应用E序的操作?br>
  • 事gQeventQ?/b> Q向监视pȝ发出的通知Q反映状态改变或者一些操作的执行Q。通知认操作或者状态改变确实发生了(jin)。通知q可以用于触发事Ӟ如对于超q设|阀|比如? 存或者磁盘空间等资源不Q的状态改变做出反应。这U通知可以用于在系l需要关注时向应用程序管理员发送电(sh)子邮件或者传呹{?/li>

? 扩展 Spring JMX Ӟ我将用一个简单的案例分别展示q三个需要关注的领域Q一个带有开始和停止Ҏ(gu)q且有一个读写属性要理的示例服务。我q要用一个小型的客户?服务? 应用E序试q个实现Qƈ开放一个?MX4J 适配器的 HTTP 理接口。所有例子将有必要的限制Q但是以(zhn)理解相应的概念。?zhn)会(x)看到在Z Spring 的应用程序方法和属性中加入 JMX 通知事g有多么容易,l果是可以监视状态改变,同时不会(x)?Java 对象中加入不必要的代码?/p>

MBeanInfo 模型

如果下蝲与本文有关的代码Q?zhn)会(x)发C个名?com.claudeduguay.mbeans.model 的包Q它包含一l用于徏?MBeanInfo XML 文g的类。这个包包含大量c,因此我不?x)详l讨论所有类Q但是其基本内容q是有必要说明的?/p>

模型的根?MBeanDescriptor c,它提供了(jin)一?createMBeanInfo() Ҏ(gu)Q负责用应用E序元数据创Z个兼? JMX ?ModelMBeanInfo 实例?code>MBeanDescriptorUtil cL供了(jin)两个?rn)态的 read() Ҏ(gu)Q它装蝲q保存这?XML 文档模型。这个模型中使用?Document ?Element 实例Z JDOM 框架?/p>

我用的基本 MBeanInfo 相关cd描述W模型是密切相关的。基cM的所有基本属性都是在 XML 中徏模的Qƈ可以用简单的格式定义。例如,<mbean> 标记是我的文档的栏V它?ModelMBeanInfo 直接相关Q它期待一?type ?description 属性。类型是受管 bean 的完全限定类名。不q,在用我?Sping 解决Ҏ(gu)Ӟq个cd全可以在上下文中z?code><mbean> 标记期待零个或者多?attribute?i>operation?i>constructor ?notification 子类型。它们每一个都提供?jin)?MBeanInfo c?XML 属性?/p>
?1. MBean XML 格式
?1. MBean XML 格式

MBean 模型实现利用?com.claudeduguay.util.jdom 包中几个?JDOM 相关的工L(fng)。它们主要是解析和构?Document ?Element 对象的接口,一个工L(fng)使读和写 Document 更Ҏ(gu)。要查看的大多数代码? com.claudeduguay.mbeans.spring 包中?/p>

已经做了(jin)_的预备工作,让我们开始扩?Spring JMX!



回页?/b>


改进 ModelMBean 中的通知

我要做的W一件事是扩?Spring JMX ModelMBean 实现Q这样就可以发送通知而不用在理的资源中直接实现q个行ؓ(f)。ؓ(f)此,q需要扩?Spring 导出器以创徏改进?ModelMBean 实例。最后,q需要用一个新的装配器从映文件中提取 MBeanInfo 元数据?/p>

ModelMBeanExtension c?/span>

扩展 RequiredModelMBean cȝ一个目的是在管理代理中透明地启用通知。这个应用程序需要三U通知Q设|属性倹{方法调用之前以?qing)方法调用之后。因为消息是我自己配|的Q在每一U情况下Q它都可以按照我需要的那样提供信息。要实现q一点,我对cd通知使用?jin)一个命名规范,其中对于样式 <matchingType>.<methodOrAttributeName> (g)查点分隔的类型名。匹配的cd必须?set?code>before 或?after 之一。如果类型是 setQ那么就认ؓ(f)是一个属性名Q否则,p为是一个方法名?/p>

扩展?ModelMBean 代码使用额外的类帮助q行耦合。第一个是 NotificationInfoMapQ它是一个用通知元数据构建的、简单的 MapQƈ与前~Q?i>set|before|afterQ点名(method|attributeQ样式相兌Q这样就可以更有效地得到匚w的通知元数据。第二个是工h法的一个静(rn)态集合。清?1 昄?jin)?f)通知而扩展的 RequiredModelMBeanQ?/p>
清单 1. ModelMBeanExtension

package com.claudeduguay.mbeans.spring;

import java.lang.reflect.*;

import javax.management.*;
import javax.management.modelmbean.*;

public class ModelMBeanExtension extends RequiredModelMBean
{
protected NotificationInfoMap notificationInfoMap;
protected ModelMBeanInfo modelMBeanInfo;
protected Object managedBean;

public ModelMBeanExtension() throws MBeanException {}

public ModelMBeanExtension(ModelMBeanInfo modelMBeanInfo)
throws MBeanException
{
super(modelMBeanInfo);
this.modelMBeanInfo = modelMBeanInfo;
notificationInfoMap = new NotificationInfoMap(modelMBeanInfo);
}

public void setModelMBeanInfo(ModelMBeanInfo modelMBeanInfo)
throws MBeanException
{
this.modelMBeanInfo = modelMBeanInfo;
notificationInfoMap = new NotificationInfoMap(modelMBeanInfo);
super.setModelMBeanInfo(modelMBeanInfo);
}

public MBeanNotificationInfo[] getNotificationInfo()
{
return modelMBeanInfo.getNotifications();
}

public void setManagedResource(Object managedBean, String type)
throws MBeanException, RuntimeOperationsException,
InstanceNotFoundException, InvalidTargetObjectTypeException
{
super.setManagedResource(managedBean, type);
this.managedBean = managedBean;
}

protected void maybeSendMethodNotification(
String type, String name) throws MBeanException
{
MBeanNotificationInfo info = notificationInfoMap.
findNotificationInfo(type, name);
if (info != null)
{
long timeStamp = System.currentTimeMillis();
String notificationType = ModelMBeanUtil.
matchType(info, "." + type + "." + name);
sendNotification(new Notification(
notificationType, this, timeStamp,
info.getDescription()));
}
}

protected void maybeSendAttributeNotification(
Attribute attribute)
throws MBeanException, AttributeNotFoundException,
InvalidAttributeValueException, ReflectionException
{
String name = attribute.getName();
MBeanNotificationInfo info = notificationInfoMap.
findNotificationInfo("set", attribute.getName());
if (info != null)
{
Object oldValue = getAttribute(name);
Object newValue = attribute.getValue();
long timeStamp = System.currentTimeMillis();
String notificationType = ModelMBeanUtil.
matchType(info, ".set." + name);
sendNotification(new AttributeChangeNotification(
this, timeStamp, timeStamp,
info.getDescription(), info.getName(),
notificationType, oldValue, newValue));
}
}

public Object invoke(
String name, Object[] args, String[] signature)
throws MBeanException, ReflectionException
{
maybeSendMethodNotification("before", name);
Object returnValue = super.invoke(name, args, signature);
maybeSendMethodNotification("after", name);
return returnValue;
}

public Object getAttribute(String name) throws MBeanException,
AttributeNotFoundException, ReflectionException
{
try
{
Method method = ModelMBeanUtil.findGetMethod(
modelMBeanInfo, managedBean, name);
return method.invoke(managedBean, new Object[] {});
}
catch (IllegalAccessException e)
{
throw new MBeanException(e);
}
catch (InvocationTargetException e)
{
throw new MBeanException(e);
}
}

public void setAttribute(Attribute attribute)
throws MBeanException, AttributeNotFoundException,
InvalidAttributeValueException, ReflectionException
{
try
{
Method method = ModelMBeanUtil.findSetMethod(
modelMBeanInfo, managedBean, attribute.getName());
method.invoke(managedBean, attribute.getValue());
maybeSendAttributeNotification(attribute);
}
catch (InvocationTargetException e)
{
throw new MBeanException(e);
}
catch (IllegalAccessException e)
{
throw new MBeanException(e);
}
}
}

不需要代理代理!

因ؓ(f) ModelMBean 已经是一U代理,所以不需要?Spring 的代理机制和 AOP 截获器来截获感兴的Ҏ(gu)?code>ModelMBean 接口需?setAttribute ?invoke Ҏ(gu)的实C理对底层受资源的调用。可以?RequiredModelMBean c,保证它出现在所?JMX 实现中,q增加我所需要的功能?/p>

我的 ModelMBeanExtension 实现?jin)同L(fng)构造函敎ͼ但是在一个实例变量中存储?ModelMBeanInfo 的一个副本。因个值可以通过构造函数或者调?setModelMBeanInfo Ҏ(gu)讄Q所以我覆盖?jin)这个方法以存储q个|调用类以完成默认的行ؓ(f)。在默认情况下,RequiredModelMBean cd加两个一般性通知描述W,因此我覆盖了(jin) getNotificationInfo() Ҏ(gu)Q只q回我描q的通知。仍然会(x)发送一般性通知Q但是要求特定通知的客户不?x)看到它们?/p>

Z(jin)发送通知Q我覆盖?setAttribute() ?invoke() Ҏ(gu)q检查调用是否匹配我的通知信息描述W。每ơ都遍历列表应该不会(x)带来很大的开销Q因为大多数cd?x)发送有限的一l通知Q但是我需要测试每一个通知可能的许多通知cd字符Ԍ而重复这一q程看来是个费。ؓ(f)?jin)保证不会(x)遇到性能问题Q我实例化了(jin)一?i>通知信息映射Q这是一个名U?信息映射Q可以用来进行快速查询。关键是一个具有类型前~Q?code>set?code>before 或?afterQ和所涉及(qing)的属性和Ҏ(gu)的简单字W串。可以?findNotificationInfo() Ҏ(gu)?setAttribute() 调用或者方法调用时查找通知信息实例?/p>

完成?jin)基架构后,可以截获对 setAttribute() ?invoke() Ҏ(gu)的调用了(jin)。属性改变需要发送一?AttributeChangeNotification 实例Q它要求有旧的属性值和新的|以及(qing)从通知信息描述W中可以得到的细节。在发送通知Ӟ如果消息序是؜qQ则要发送序列号Q让客户机应用程序可以对消息排序。ؓ(f)?jin)简化,我用了(jin)当前旉戌不是管理一个计数器。创建通知对象ӞsendNotification() Ҏ(gu)保证它会(x)发布。对?invoke() Ҏ(gu)使用同样的思\Q尽在q里我用了(jin)更简单的 Notification 对象。可以调用超cM?invoke() Ҏ(gu)同时(g)查这两者(before ?afterQ,q根据查扄果发?before ?after 通知?/p>

回页?/b>


扩展 Spring JMX 导出?/span>

Z(jin)使用扩展?ModelMBeanQ需要覆?Spring MBeanExporter 中的 createModelMBean() Ҏ(gu)。因为可以注入装配器属性,所以必ȝ道它可能不是我所期待的这一事实。可以在构造函C讄所需要的装配器,但是当装配器改变旉要返回一个普?ModelMBean。所要做的就是缓存一?MBeanInfoAssembler 的本地引用,q在创徏新的 ModelMBean 时检查它是什么类型的。清?2 昄?jin)所有这些改变:(x)


清单 2. MBeanDescriptorEnabledExporter

package com.claudeduguay.mbeans.spring;

import javax.management.*;
import javax.management.modelmbean.*;

import org.springframework.jmx.export.*;
import org.springframework.jmx.export.assembler.*;

public class MBeanDescriptorEnabledExporter extends MBeanExporter
{
protected MBeanInfoAssembler mBeanInfoAssembler;

public MBeanDescriptorEnabledExporter()
{
setAssembler(new MBeanDescriptorBasedAssembler());
}

public ModelMBean createModelMBean() throws MBeanException
{
if (mBeanInfoAssembler instanceof MBeanDescriptorBasedAssembler)
{
return new ModelMBeanExtension();
}
return super.createModelMBean();
}

public void setAssembler(MBeanInfoAssembler mBeanInfoAssembler)
{
this.mBeanInfoAssembler = mBeanInfoAssembler;
super.setAssembler(mBeanInfoAssembler);
}
}

在用这个扩展的cLQ可以用标准 Spring 语言改变装配器,q在需要时回到默认的行为。在大多数情况下Q如果最l绕q扩展,那么׃值得使用q个版本。不q,如果惌以新的定制装配器使用扩展?ModelMBeanQ那么现在可以这样做?/p>

回页?/b>


构徏一个定制的装配?/span>

q个定制装配器的主要d是查找与理的类有关的元数据映射文g。找到这个文件后Q就装蝲它ƈ生成必要?ModelMBeanInfo 实例。ؓ(f)此,我只是实C(jin) Spring MBeanInfoAssembler 实例建立q个文g的相关类路径Q用?rn)? MBeanDescriptorUtil.read() Ҏ(gu)装蝲它ƈq回l果Q如清单 3 所C:(x)


清单 3. MBeanDescriptorBasedAssembler

package com.claudeduguay.mbeans.spring;

import java.io.*;

import javax.management.modelmbean.*;

import org.springframework.core.io.*;
import org.springframework.jmx.export.assembler.*;

import com.claudeduguay.mbeans.model.*;

public class MBeanDescriptorBasedAssembler
implements MBeanInfoAssembler
{
public ModelMBeanInfo getMBeanInfo(
Object managedBean, String beanKey)
{
String name = managedBean.getClass().getName();
String path = name.replace('.', '/') + ".mbean.xml";

ClassPathResource resource = new ClassPathResource(path);
InputStream input = null;
try
{
input = resource.getInputStream();
MBeanDescriptor descriptor = MBeanDescriptorUtil.read(input);
return descriptor.createMBeanInfo();
}
catch (Exception e)
{
throw new IllegalStateException(
"Unable to load resource: " + path);
}
finally
{
if (input != null)
{
try { input.close(); } catch (Exception x) {}
}
}
}
}

q个 MBeanDescriptorBasedAssembler 忽略 bean 键参数ƈ直接用受?bean 引用创徏所需?ModelMBeanInfo 实例?/p>

回页?/b>


CZ

在本文其余部分,我将着重展C?Spring JMX 扩展的用。ؓ(f)此,使用一个假想的服务Q它开放两个方法和一个属性,因此表现?jin)典型的用例?/p>

ExampleService 是一?Java 对象Q它在被调用时只是向控制台进行输出,如清?4 所C:(x)


清单 4. ExampleService

package com.claudeduguay.jmx.demo.server;

public class ExampleService
{
protected String propertyValue = "default value";

public ExampleService() {}

public String getPropertyValue()
{
System.out.println("ExampleService: Get Property Value");
return propertyValue;
}

public void setPropertyValue(String propertyValue)
{
System.out.println("ExampleService: Set Property Value");
this.propertyValue = propertyValue;
}

public void startService()
{
System.out.println("ExampleService: Start Service Called");
}

public void stopService()
{
System.out.println("ExampleService: Stop Service Called");
}
}

对管理员友好的消?/span>

q个扩展的描q符可以几乎直接兌属性和操作。描q符Ҏ(gu)优于内省式方法的主要一Ҏ(gu)可以提供更特定的消息。通知描述W的配置选项有赖于类型(XMLQ属性的命名规范。实际的名字是Q意的Q但是代码会(x)被类型中?set.name?code>before.name ?after.name 样式触发。在q种情况下,我将 set 通知?propertyValue QJMXQ属性关联,?before ?after 通知?startService() ?stopService() Ҏ(gu)兌。同Pq些扩展使我可以很好利用描述性的消息?/p>

在清?5 中,可以看到定义?jin)一个属性和两个Ҏ(gu)。通知描述W定义了(jin)Ҏ(gu)的之前和之后事g以及(qing)一个属性设|通知Q?/p>
清单 5. ExampleService.mbean.xml

<?xml version="1.0"?>
<mbean name="ExampleService" description="Example Service"
type="com.claudeduguay.jmx.demo.server.ExampleService">

<attribute name="propertyValue"
description="Property Value Access" type="java.lang.String"
readable="true" writable="true" />

<operation name="stopService"
description="Stop Example Service" />
<operation name="startService"
description="Start Example Service" />

<notification name="PropertyValueSet"
types="example.service.set.propertyValue"
description="PropertyValue was set" />
<notification name="BeforeStartService"
types="example.service.before.startService"
description="Example Service is Starting" />
<notification name="AfterStartService"
types="example.service.after.startService"
description="Example Service is Started" />
<notification name="BeforeStopService"
types="example.service.before.stopService"
description="Example Service is Stopping" />
<notification name="AfterStopService"
types="example.service.after.stopService"
description="Example Service is Stopped" />

</mbean>



回页?/b>


配置服务?/span>

要在客户?服务器环境中q行q个例子Q需要配|和启动一?MBeanServer 实例。ؓ(f)此,我?Java 5.0 MBeanServer 实例Q它保证我可以?JVM 中提供的理扩展Q同时管理自q代码。如果愿意,q可以运?MBeanServer 的多个实例,(zhn)愿意的话也可以自己试一试作为练?fn)?/p>

像 Java 5.0 一PSpring 框架使?zhn)可以配置自己?MBeanServer 实例。我选择使用 Java 5.0Q因为它支持 JSR-160 q接器,我的客户Z码会(x)需要它?/p>
清单 6. SpringJmxServer

package com.claudeduguay.jmx.demo.server;

import org.springframework.context.*;
import org.springframework.context.support.*;

import mx4j.tools.adaptor.http.*;

/*
* To use the SpringJmxServer, use the following command line
* arguments to activate the Java 1.5 JMX Server.
*
* -Dcom.sun.management.jmxremote.port=8999
* -Dcom.sun.management.jmxremote.ssl=false
* -Dcom.sun.management.jmxremote.authenticate=false
*/

public class SpringJmxServer
{
public static void main(String[] args)
throws Exception
{
String SPRING_FILE =
"com/claudeduguay/jmx/demo/server/SpringJmxServer.xml";
ApplicationContext context =
new ClassPathXmlApplicationContext(SPRING_FILE);
HttpAdaptor httpAdaptor =
(HttpAdaptor)context.getBean("HttpAdaptor");
httpAdaptor.start();
}
}

׃有了(jin) MBeanDescriptorEnabledExporterQ服务器?Spring 配置文g非常单。除?jin)声?ExampleServiceQ我增加?jin)开放一?HTTP 适配器和q接 XSLTProcessor ?HttpAdaptor 所需要的 MX4J V注意这?Spring ?IOC 实现非常有用的一个领域。清?7 昄?jin)我? SpringJmxServer 实例?Spring 配置文gQ?/p>
清单 7. SpringJmxServer.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="exporter" class=
"com.claudeduguay.mbeans.spring.MBeanDescriptorEnabledExporter">
<property name="beans">
<map>
<entry key="Services:name=ExampleService"
value-ref="ExampleService" />
<entry key="MX4J:name=HttpAdaptor"
value-ref="HttpAdaptor" />
<entry key="MX4J:name=XSLTProcessor"
value-ref="XSLTProcessor" />
</map>
</property>
</bean>

<bean id="XSLTProcessor"
class="mx4j.tools.adaptor.http.XSLTProcessor" />
<bean id="HttpAdaptor"
class="mx4j.tools.adaptor.http.HttpAdaptor">
<property name="processor" ref="XSLTProcessor"/>
<property name="port" value="8080"/>
</bean>

<bean id="ExampleService"
class="com.claudeduguay.jmx.demo.server.ExampleService" />

</beans>

如果愿意Q假定?zhn)遵@?jin)我的设|)(j)Q那么现在就可以q行q个服务器了(jin)。它?x)注?ExampleService q运?HTTP 适配器。不要忘C用注释中提到的命令行参数启动 Java 5.0 MBeanServerQ否则会(x)得到默认实例Q客hCZ׃能工作了(jin)?/p>

回页?/b>


q行客户Z?/span>

启动服务器后Q可以运行如清单 8 所C的客户Z码看看会(x)发生什么。这D代码实C(jin) JMX NotificationListener 接口Q这样就可以交互式地看到所发生的事情。连接后Q可以注册监听器Q然后触发几个调用、启动和停止服务、设|和取得属性。在每一U情况下Q都应当在控制台上看C个确认操作的通知消息?/p>
清单 8. SpringJmxClient

package com.claudeduguay.jmx.demo.client;

import java.util.*;

import javax.management.*;
import javax.management.remote.*;

public class SpringJmxClient implements NotificationListener
{
public void handleNotification(
Notification notification, Object handback)
{
System.out.println(
"Notification: " + notification.getMessage());
}

public static void main(String[] args)
throws Exception
{
SpringJmxClient listener = new SpringJmxClient();

String address =
"service:jmx:rmi:///jndi/rmi://localhost:8999/jmxrmi";
JMXServiceURL serviceURL = new JMXServiceURL(address);
Map<String,Object> environment = null;
JMXConnector connector =
JMXConnectorFactory.connect(serviceURL, environment);
MBeanServerConnection mBeanConnection =
connector.getMBeanServerConnection();

ObjectName exampleServiceName =
ObjectName.getInstance("Services:name=ExampleService");
mBeanConnection.addNotificationListener(
exampleServiceName, listener, null, null);

mBeanConnection.invoke(
exampleServiceName, "startService", null, null);
mBeanConnection.setAttribute(exampleServiceName,
new Attribute("propertyValue", "new value"));
System.out.println(mBeanConnection.getAttribute(
exampleServiceName, "propertyValue"));
mBeanConnection.invoke(
exampleServiceName, "stopService", null, null);
}
}

׃ HTTP 适配器也是可用的Q可以试着使用 MX4J Q通过一个到端口 8080 的浏览器q接Q管理同L(fng)Ҏ(gu)和属性。如果同时让客户Z码运行,那么也会(x)看到q些操作的通知?/p>

回页?/b>


l束?/span>

? 本文中,我展CZ(jin)如何扩展 Spring ?JMX 支持以满_用程序的特定需求。在q里Q我使用?Spring 的基于容器的体系l构? AOP 框架来ؓ(f) JMX Ҏ(gu)和属性增加通知事g。当?dng)我只触?qing)C(jin) Spring JMX 能力的皮毛。还可以有许多其他扩展,Spring ? JMX 都是很大的主题,每一个都值得q一步研I。我(zhn)研I本文的源代码ƈ参阅后面 参考资?/a> 一节以?jin)解更多关?Spring JMX 和相x术的内容?/p>


回页?/b>


下蝲

描述名字大小 下蝲Ҏ(gu)
Source codej-Extending-Spring-JMX.jar22 KB  FTP
Source codej-Extending-Spring-JMX-src.zip3 MB  FTP
关于下蝲Ҏ(gu)的信?/a>获取 Adobe] Reader]


回页?/b>


参考资?

学习(fn)

获得产品和技?/b>

讨论
  • 加入本文?a href="javascript:void forumWindow()">论坛 ?(zhn)也可以通过点击文章剙或者底部的论坛链接参加讨论?

  • developerWorks blogsQ参?developerWorks C֌?


回页?/b>


关于作?/span>

Claude ?Capital Stream Inc 的高U?J2EE 架构师。他有超q?25 q的软g开发经验,q且?Java q_的第一?beta 版本发布时就开始用它?jin)。Claude 已发表了(jin)过 75 文章和 过 150 书评,主要x Java 语言?XML?



Dion 2005-12-09 23:23 发表评论
]]>
վ֩ģ壺 jizz߹ۿ| һƷ| ޾ƷӰԺ| ԲľƷƵѿ| 椸Ƶ| ëƬvipԱ߿| ŮƬѹۿƵ| 99ƷƵ| 97߹ۿƵ| ŮվѸƵ| žӰ߹ۿѸ| 91Ƶ| ѹۿaƬ| ִִˬƵ | һػɫѴƬƵ| ŮվɫƵ| 鶹va߾ƷѲ| һëƬaaaaaaƵѿ| ĻһƵ| ˮƵ߹ۿѲŸ| ѾƷ99þùۺϾƷ| ĻƷƵѹۿ| þþþѿAƬAPP| ɫƬѹۿ| վwww߹ۿ| ޾ƷۺҰ| þ޾ƷAVӣ| Ʒ޾Ʒ| AVAVպAVվ| һëƬaѲɫӰ| 99þѹƷ| 57paoƵ| þWWW˳Ƭ| gogoȫ| ޹߹ۿ| 91ҹƷһ| ŷ߹ۿ| ĻƵ| ŷxxxxx| ޾Ʒ鶼| ձһ߶ |