研究Spring Framework源码,启动Spring容器时发现系统出来这么一句log:
14:32:40.348 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'spring.liveBeansView.mbeanDomain' in PropertySource 'systemProperties' with value of type String
这个’spring.liveBeansView.mbeanDomain’是干嘛用的?不由激起了我的好奇心。
查了资料发现,这是个用来暴露MBean的环境变量。那么MBean又是什么呢?
继续百度,发现这是个挺有用的功能,就是提供Bean的远程调用。通常我们的Bean都是由Spring启动时通过读取配置加载进Spring容器的,这个很好很方便,我们可以让Spring去管理我们的Bean的生成、配置以及Bean与Bean之间的依赖。但是Spring一旦启动完毕,再想去修改Bean的配置,就要用到JMX了。JMX技术的前提就是你得提供MBean,那么怎么把我们的Spring Bean变为MBean呢?
我们先来看一个普通Spring Bean的调用例子。
2.新建一个Person类。
package com.example.demo;
public class Person {
String name;
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
3.新建mbeanTest.xml配置文件。
4.修改系统生成的SpringMbeanTestApplication类的Main函数。
package com.example.demo;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@SpringBootApplication
public class SpringMbeanTestApplication {
public static void main(String[] args) {
// SpringApplication.run(SpringIocTestApplication.class, args);
ApplicationContext ctx = new ClassPathXmlApplicationContext("mbeanTest.xml");
Person person1 = (Person) ctx.getBean("person1");
System.out.println(person1.getName() + "," + person1.getAge());
}
}
5.运行结果如下:
14:32:40.205 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2ff5659e
14:32:40.275 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 1 bean definitions from class path resource [mbeanTest.xml]
14:32:40.297 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'person1'
14:32:40.348 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'spring.liveBeansView.mbeanDomain' in PropertySource 'systemProperties' with value of type String
Mike,23
这个例子里我们通过配置将id为person1的bean放入Spring容器中,然后通过getBean方法又读了出来,并显示了这个bean的name属性和age属性。
OK,接下来我们改造一下这个Bean。
6.先定义一个MBeanBase接口类(什么名字不重要,是interface类型就行),这个接口我们要求它有个sayHello方法。
package com.example.demo;
public interface MBeanBase {
public void sayHello();
}
7.然后让Person类实现这个接口。
package com.example.demo;
public class Person implements MBeanBase{
String name;
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void sayHello() {
System.out.println("Hello," + name);
}
}
8.在mbeanTest.xml中加入MBean的配置。
9.在SpringMbeanTestApplication类的Main函数打印bean属性那一行打个断点,然后用DEBUG模式运行,
程序停在我们打断点的那一行。
10.打开一个命令行窗口,输入jconsole,弹出java控制台。选择本地进程中我们的SpringMbeanTestApplication进程。
11.在MBean标签页可以看到我们定义的bean,将它的name属性值改为“Jane”,让程序跑完。
运行结果如下:
16:51:19.447 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@589b3632
16:51:20.107 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 2 bean definitions from class path resource [mbeanTest.xml]
16:51:20.616 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'person1'
16:51:20.926 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'exporter'
16:51:20.960 [main] DEBUG org.springframework.jmx.support.JmxUtils - Found MBeanServer: com.sun.jmx.mbeanserver.JmxMBeanServer@46f5f779
16:51:20.961 [main] DEBUG org.springframework.jmx.export.MBeanExporter - Registering beans for JMX exposure on startup
16:51:20.992 [main] DEBUG org.springframework.jmx.export.MBeanExporter - Located managed bean 'bean:name=HelloMBean': registering with JMX server as MBean [bean:name=HelloMBean]
16:51:21.071 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'spring.liveBeansView.mbeanDomain' in PropertySource 'systemProperties' with value of type String
Jane,23
可以看到,我们在Spring容器外部,对Spring容器中的bean属性值进行了修改,这就很厉害了。
在网络环境下,可以通过远程调用,达到不用重启服务就能修改配置的目的。
注:上面的MBeanBase类中我们定义了一个sayHello方法,在本文中其实并没调用到,下次写个Web工程远程调用下试试看。