[Spring Framework]如何将Spring bean变为MBean

研究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的调用例子。

1.新建一个Spring工程。
[Spring Framework]如何将Spring bean变为MBean_第1张图片

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());

	}
}

整个目录结构如下:
[Spring Framework]如何将Spring bean变为MBean_第2张图片

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模式运行,
程序停在我们打断点的那一行。
[Spring Framework]如何将Spring bean变为MBean_第3张图片

10.打开一个命令行窗口,输入jconsole,弹出java控制台。选择本地进程中我们的SpringMbeanTestApplication进程。
[Spring Framework]如何将Spring bean变为MBean_第4张图片
[Spring Framework]如何将Spring bean变为MBean_第5张图片
11.在MBean标签页可以看到我们定义的bean,将它的name属性值改为“Jane”,让程序跑完。

[Spring Framework]如何将Spring bean变为MBean_第6张图片

运行结果如下:

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工程远程调用下试试看。

你可能感兴趣的:(Java,spring,boot,spring,cloud)