JMX(Java Manage-ment Extensions)Java管理扩展:改变运行中应用的配置
一、将Spring Bean导出为MBean
/**
* 在Spring中声明一个 MBeanExporter, 将spittleController bean导出为一个模型MBean
* @param spittleController
* @return
*/
@Bean
public MBeanExporter mBeanExporter(SpittleController spittleController){
MBeanExporter exporter = new MBeanExporter();
Map<String, Object> beans = new HashMap<>();
beans.put("spitter:name=SpittleController", spittleController);
exporter.setBeans(beans);
return exporter;
}
从命令行启动JConsole:
使JDK在PATH上,然后输入jconsole 即可:

进入之后,就可以动态修改正在运行中程序的属性值了:
二、通过名称暴露方法
如果不做限制,所有public成员被导出为MBean的操作或属性,如下图:

/**
* 在Spring中声明一个 MBeanExporter, 将spittleController bean导出为一个模型MBean
* 同时配置 MBeanInfoAssembler , 限制某些方法将在MBean上暴露
* @param spittleController
* @return
*/
@Bean
public MBeanExporter mBeanExporter(SpittleController spittleController, MBeanInfoAssembler assembler){
MBeanExporter exporter = new MBeanExporter();
Map<String, Object> beans = new HashMap<>();
beans.put("spitter:name=SpittleController", spittleController);
exporter.setBeans(beans);
exporter.setAssembler(assembler);
return exporter;
}
/**
* 通过名称暴露方法,限制哪些方法和属性将在MBean上暴露
* @return
*/
@Bean
public MethodNameBasedMBeanInfoAssembler assembler(){
MethodNameBasedMBeanInfoAssembler assembler =
new MethodNameBasedMBeanInfoAssembler();
assembler.setManagedMethods(new String[]{
"getSpittlesPerPage","setSpittlesPerPage"
});
return assembler;
}

除了上面这种方法外,还可以通过另外三种方法:配置MethodExclusionMBeanInfoAssembler、通过InterfaceBasedMBeanInfoAssembler接口、使用注解驱动的MBean。
注解的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:mbean-export/>
</beans>
处理MBean冲突:
有三种机制: FAIL_ON_EXISTING、IGNORE_EXISTING、REPLACING_EXISTING
@Bean
public MBeanExporter mBeanExporter(SpittleController spittleController, MBeanInfoAssembler assembler){
MBeanExporter exporter = new MBeanExporter();
Map<String, Object> beans = new HashMap<>();
beans.put("spitter:name=SpittleController", spittleController);
exporter.setBeans(beans);
exporter.setAssembler(assembler);
// 处理冲突
exporter.setRegistrationPolicy(RegistrationPolicy.IGNORE_EXISTING);
return exporter;
}
三、远程MBean
3.1 暴露远程MBean
注意两点:一、配置RmiRegistryFactoryBean和配置ConnectorServerFactoryBean的顺序不能颠倒;二、端口不能为1099;
(关于第一点参考了:https://www.iteye.com/topic/358379)
/**
* 通过RmiRegigstryFactoryBean来启动一个RMI注册表
* @return
*/
@Bean
public RmiRegistryFactoryBean rmiRegistryFactoryBean(){
RmiRegistryFactoryBean rmiRegistryFactoryBean = new RmiRegistryFactoryBean();
rmiRegistryFactoryBean.setPort(1199);
return rmiRegistryFactoryBean;
}
/**
* 是MBean导为远程对象
* 使用RMI远程访问
* 将ConnectorServerFactoryBean
* @return
*/
@Bean
public ConnectorServerFactoryBean connectorServerFactoryBean(){
ConnectorServerFactoryBean connectorServerFactoryBean = new ConnectorServerFactoryBean();
connectorServerFactoryBean.setServiceUrl("service:jmx:rmi://localhost/jndi/rmi://localhost:1199/spittle");
/*try {
connectorServerFactoryBean.setObjectName("connector:name=rmi");
} catch (MalformedObjectNameException e) {
throw new RuntimeException(e);
}*/
return connectorServerFactoryBean;
}
3.2、 访问远程MBean
配置:
/**
* @Date 2019-05-03
* @Author lifei
*/
@Configuration
public class MBeanConfig {
/**
* 该bean用于访问基于RMI的远程服务器,它能够以MBeanServerConnection的形式注入到其他bean中
* @return
*/
@Bean
public MBeanServerConnectionFactoryBean connectionFactoryBean(){
MBeanServerConnectionFactoryBean mBeanServerConnectionFactoryBean =
new MBeanServerConnectionFactoryBean();
try {
mBeanServerConnectionFactoryBean.setServiceUrl("service:jmx:rmi://localhost/jndi/rmi://localhost:1199/spittle");
return mBeanServerConnectionFactoryBean;
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}
操作:
/**
* 获取属性值
*/
@Test
public void showSpittleName(){
try {
Object spittlesPerPage = mBeanServerConnection.getAttribute(new ObjectName("spitter:name=SpittleController"),
"SpittlesPerPage");
System.out.println(spittlesPerPage);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 设置值
*/
@Test
public void reSetSpittlesPerPage(){
try {
mBeanServerConnection.setAttribute(new ObjectName("spitter:name=SpittleController"),
new Attribute("SpittlesPerPage", 3));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 通过调用方法设置值
*/
@Test
public void invokSetSpittlesPerPage(){
try {
mBeanServerConnection.invoke(new ObjectName("spitter:name=SpittleController"),
"setSpittlesPerPage", new Object[]{5}, new String[]{"int"});
} catch (Exception e) {
e.printStackTrace();
}
}
在按照《Spring in Action》实践处理通知部分的时候:
监听通知部分没有实践出来
本文围绕JMX(Java管理扩展)展开,介绍将Spring Bean导出为MBean的方法,可从命令行启动JConsole动态修改运行程序属性值。还阐述通过名称暴露方法的多种途径及处理MBean冲突的机制,最后讲解远程MBean的暴露与访问,包括配置注意事项。
8万+

被折叠的 条评论
为什么被折叠?



