Springboot sentiment edify-JMX analysis

Source: Internet
Author: User
Tags tojson

To undertake the former Wen springboot sentiment edify [email protected] annotation analysis, the recent project in contact with the use of JMX protocol framework, then on the basis of the previous article on how to integrate JMX Springboot

Knowledge Reserve

Jmx:java Management Extension (Java Management application extension), this mechanism can easily manage and monitor running Java programs. Often used to monitor management threads, memory, log level, service restart, system environment, and so on.
More knowledge points refer to this article: 52800742. I refer to the framework diagram here to facilitate understanding

Jmxautoconfiguration

Springboot by specifying the enableautoconfiguration property value in the meta-inf\spring.factories file as Jmxautoconfiguration, the basic structure of the JMX framework mold. Sounds very magical, the author of this analysis of the source to a glimpse of the

Annotations

First look at the annotations on the jmxautoconfiguration head.

@Configuration@ConditionalOnClass({ MBeanExporter.class })@ConditionalOnProperty(prefix = "spring.jmx", name = "enabled", havingValue = "true", matchIfMissing = true)public class JmxAutoConfiguration implements EnvironmentAware, BeanFactoryAware {}

If you want to make the JMX environment effective,

  • Classpath environment to exist Org.springframework.jmx.export.MBeanExporter class

  • environment variable spring.jmx.enabled set to True, default is True

General introduction Springboot The above conditions are satisfied, but users can switch the JMX environment by spring.jmx.enabled Properties

@Bean method

There are three methods, which are modified by @Bean and @Conditional annotated respectively. The author in turn to interpret

jmxautoconfiguration#objectnamingstrategy ()-Gets the build policy of the ObjectName

    @Bean    @ConditionalOnMissingBean(value = ObjectNamingStrategy.class, search = SearchStrategy.CURRENT)    public ParentAwareNamingStrategy objectNamingStrategy() {        // create namingStrategy        ParentAwareNamingStrategy namingStrategy = new ParentAwareNamingStrategy(                new AnnotationJmxAttributeSource());        // have a try to read environment property 'spring.jmx.default-domain'        String defaultDomain = this.environment.getProperty("spring.jmx.default-domain");        if (StringUtils.hasLength(defaultDomain)) {            namingStrategy.setDefaultDomain(defaultDomain);        }        return namingStrategy;    }

The above code is also very simple, where the environment variable spring.jmx.default-domain represents the JMX Default domain mount.

    • If the @ManagedResource does not specify the objectName attribute or beanname does not conform to the JMX syntax, the current class's package name is selected by default as ObjectName

jmxautoconfiguration#mbeanserver ()-Create Mbeanserver

    @Bean    @ConditionalOnMissingBean    public MBeanServer mbeanServer() {        // 1.first to search classpath exsit 'weblogic.management.Helper'/'com.ibm.websphere.management.AdminServiceFactory' class if or not          SpecificPlatform platform = SpecificPlatform.get();        if (platform != null) {            return platform.getMBeanServer();        }        // 2.via MBeanServerFactoryBean to create MBeanServer        MBeanServerFactoryBean factory = new MBeanServerFactoryBean();        factory.setLocateExistingServerIfPossible(true);        factory.afterPropertiesSet();        return factory.getObject();    }

The author here only focuses on how Mbeanserverfactorybean is creating mbeanserver, directly to see its implementation of the Afterpropertiesset () method

    @Override    public void afterPropertiesSet() throws MBeanServerNotFoundException {        // 1.尝试去找寻已存在的mbeanserver        if (this.locateExistingServerIfPossible || this.agentId != null) {            try {                this.server = locateMBeanServer(this.agentId);            }            catch (MBeanServerNotFoundException ex) {                if (this.agentId != null) {                    throw ex;                }                logger.info("No existing MBeanServer found - creating new one");            }        }        // 2.如果上述不存在mbeanserver,则调用jmx api生成mbeanserver        if (this.server == null) {            this.server = createMBeanServer(this.defaultDomain, this.registerWithFactory);            this.newlyRegistered = this.registerWithFactory;        }    }

The main call JMX API Mbeanserverfactory.creatembeanserver () method to create the Mbeanserver, the specific creation process I do not delve into, interested readers can analyze their own

Jmxautoconfiguration#mbeanexporter ()-Create Mbeanexporter
The source code is as follows

    @Bean    @Primary    @ConditionalOnMissingBean(value = MBeanExporter.class, search = SearchStrategy.CURRENT)    public AnnotationMBeanExporter mbeanExporter(ObjectNamingStrategy namingStrategy) {        // 1.创建注解类型的AnnotationMBeanExporter,表明采取注解方式加载mbean        AnnotationMBeanExporter exporter = new AnnotationMBeanExporter();        exporter.setRegistrationPolicy(RegistrationPolicy.FAIL_ON_EXISTING);        // 2.set above namingStrategy        exporter.setNamingStrategy(namingStrategy);        // 3.set mbeanserver via spring applicationContext        String serverBean = this.environment.getProperty("spring.jmx.server",                "mbeanServer");        if (StringUtils.hasLength(serverBean)) {            exporter.setServer(this.beanFactory.getBean(serverBean, MBeanServer.class));        }        return exporter;    }

Create the Annotationmbeanexporter class to read the Mbean of the annotated mode, and first read the Mbeanserver from the spring context.

    • environment variable spring.jmx.server if not specified, the Mbeanserver object that Beanname is ' mbeanserver ' is read by default, which is associated with jmxautoconfiguration# Mbeanserver () method registered beans coincide

Through the above analysis can be obtained, the author found that the final exposure to the outside world to invoke the JMX protocol is done through the Annotationmbeanexporter , which also contains a parsing Mbean related annotations of the mystery

Annotationmbeanexporter

The common interface for its implementation is Initializingbean/smartinitializingsingleton/disposablebean and mbeanexportoperations

constructor function
    public AnnotationMBeanExporter() {        setNamingStrategy(this.metadataNamingStrategy);        setAssembler(this.metadataAssembler);        setAutodetectMode(AUTODETECT_ALL);    }

Basically setting the underlying properties

Afterpropertiesset ()

The Initializingbean interface implementation class is as follows

    @Override    public void afterPropertiesSet() {        // have a try to find exsiting mbeanserver        if (this.server == null) {            this.server = JmxUtils.locateMBeanServer();        }    }
Aftersingletonsinstantiated ()

The Smartinitializingsingleton interface implementation class is as follows

    @Override    public void afterSingletonsInstantiated() {        try {            logger.info("Registering beans for JMX exposure on startup");            registerBeans();            registerNotificationListeners();        }        catch (RuntimeException ex) {            // Unregister beans already registered by this exporter.            unregisterNotificationListeners();            unregisterBeans();            throw ex;        }    }

Here the Registerbeans () method is mbeanserver to register the Mbean process, you can continue to track the next

    protected void Registerbeans () {///the Beans property is null, for example if we is relying solely on AUT        Odetection.            if (This.beans = = null) {This.beans = new hashmap<> ();            Use Autodetect_all as the default in no beans specified explicitly.            if (This.autodetectmode = = null) {This.autodetectmode = Autodetect_all;        }}//Perform autodetection, if desired.        int mode = (This.autodetectmode! = null? this.autodetectMode:AUTODETECT_NONE); if (mode! = Autodetect_none) {if (this.beanfactory = = null) {throw new Mbeanexportexception ("C            Annot AutoDetect MBeans If not running in a beanfactory "); } if (mode = = Autodetect_mbean | | mode = = autodetect_all) {//AutoDetect any beans that is ALR                Eady MBeans.                Logger.debug ("autodetecting user-defined JMX MBeans"); AutoDetect (This.beans, (Beanclass, Beanname), Ismbean (Beanclass));            }//Allow the assembler a chance-vote for bean inclusion. if (mode = = Autodetect_assembler | | mode = autodetect_all) && this.assembler instanceof Autod Etectcapablembeaninfoassembler) {AutoDetect (This.beans, (Autodetectcapablembeaninfoassembler) this.assemb            LER):: Includebean); }}//Mbeanserver register Mbeans if (!this.beans.isempty ()) {This.beans.forEach ((Beanna        Me, instance)-Registerbeannameorinstance (instance, beanname)); }    }

To avoid the visual fatigue caused by long code, the author summarizes the key methods here.

    1. The function of the AutoDetect () method is to traverse all the beandefinition on the Bean factory and find the qualifying beans for subsequent Mbeans registrations. The search condition boils down to the following
      • @MBeanclasses that carry annotations
      • Dynamicbean interface Implementation Class
      • *MBeanImplementation class of the interface
      • @ManagedResourceclasses that carry annotations
    2. The registerbeannameorinstance () method registers the Mbean with the eligible beans, with the following steps:
      1. Generates ObjectName objects based on the properties of annotations on a class @ManagedResource objectName
      2. If the eligible Mbean is carrying @ManagedResource annotations, the Modelbean object is generated and read @ManagedOperation , @ManagedAttribute etc. jmx annotations
      3. Finally register the above Mbean to Mbeanserver

Through the above operation can be the search to the Mbean registered to the Mbeanserver, as long as the user @ManagedOperation , @ManagedAttribute , annotated with @ManagedResource can

By-laws

Pom Content

<?xml version= "1.0" encoding= "UTF-8"? ><project xmlns= "http://maven.apache.org/POM/4.0.0" xmlns:xsi= "http ://www.w3.org/2001/XMLSchema-instance "xsi:schemalocation=" http://maven.apache.org/POM/4.0.0 Http://maven.apache . org/xsd/maven-4.0.0.xsd "> <modelVersion>4.0.0</modelVersion> <groupid>com.example</ groupid> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging >jar</packaging> <name>demo-springboot</name> <description>demo Project for Spring BOOT&L t;/description> <parent> <groupId>org.springframework.boot</groupId> <artifactid& Gt;spring-boot-starter-parent</artifactid> <version>2.0.3.RELEASE</version> <relativepa Th/> <!--lookup parent from repository to </parent> <properties> <project.build.sou Rceencoding>utf-8</project.build.sourCeencoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <ja            va.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> &LT;ARTIFACTID&GT;SPRING-BOOT-STARTER&LT;/ARTIFACTID&G        T            </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> &LT;/DEP endency> </dependencies> <build> <plugins> <plugin> < Groupid>org.springframework.boot</groupid> <artifactid>spring-boot-maven-plugin</artifact id> </plugin> </plugins> </build></project>

Mbean creation

Package Com.hundsun.quote.server.monitor;...import java.util.hashmap;import java.util.map;/** * Common Monitor MBean for system and Application * * @author Nanco * @create 2018/8/6 **/@Configuration @managedresource (value = "Monitor:name=sy Stemcommonmonitor ") public class Syscommonmonitormbean implements Initializingbean {private static Abstractmonitorserv    Ice Commonmonitorservice;    Private Gson Gson = new Gson ();    @Autowired private ApplicationContext Springapplicationcontext; @Override public void Afterpropertiesset () throws Exception {Assert.notnull (Springapplicationcontext, "Spring a        Pplicationcontext is not autowired "); Commonmonitorservice = Springapplicationcontext.getautowirecapablebeanfactory (). Createbean (    Commonmonitorservice.class); } @ManagedAttribute Public String getsystemcommoninfo () {map<string, string> systemmap = new HASHMAP&L        T;> (8);        Systemmap.put ("Syscpuratio", Commonmonitorservice.getsyscpuratio ());Systemmap.put ("Syscurrenttime", Commonmonitorservice.getsyscurrenttime ());        Systemmap.put ("Sysstartuptime", Commonmonitorservice.getsysstartuptime ());        Systemmap.put ("Sysmemoryratio", Commonmonitorservice.getsysmemoryratio ());        Systemmap.put ("Sysdisktotal", Commonmonitorservice.getsysdisktotal ());        Systemmap.put ("Sysdiskfree", Commonmonitorservice.getsysdiskfree ());    Return Gson.tojson (SYSTEMMAP); } @ManagedAttribute Public String getappcommoninfo () {map<string, string> applicationmap = new HashMap        <> (4);        Applicationmap.put ("Appcpuratio", Commonmonitorservice.getappcpuratio ());        Applicationmap.put ("Appmemoryratio", Commonmonitorservice.getappmemoryratio ());        Applicationmap.put ("Appstartuptime", Commonmonitorservice.getappstartuptime ());    Return Gson.tojson (APPLICATIONMAP); }}
Package Com.jing.quote.server.monitor;....import Org.springframework.context.annotation.configuration;import Org.springframework.jmx.export.annotation.managedoperation;import Org.springframework.jmx.export.annotation.managedoperationparameter;import Org.springframework.jmx.export.annotation.managedoperationparameters;import Org.springframework.jmx.export.annotation.managedresource;import Javax.annotation.resource;import Java.util.List ;/** * Trade Date Mbean * * @author Nanco * @create 2018/8/6 **/@Configuration @managedresource (value = "Monitor:name=trade    Datemonitor ") public class Tradedatemonitormbean {private static final String Ok_resp =" Execute success! ";    private static final String Fail_resp = "Execute fail!";    Private Gson Gson = new Gson ();    @Resource private Dstradedateservice Tradedateservice;    @Resource private Dsbaseservice Baseservice; @ManagedOperation (Description = "SELECT_ALL_TRADE_DATE_EXCL") public String selectalltradedateexcl () {LIST&LT        tradedateexcl> tradedateexcls = Tradedateservice.selectalltradedateexcl ();    Return Gson.tojson (TRADEDATEEXCLS); } @ManagedOperation (description = "Insert_trade_date_excl") @ManagedOperationParameters (value = {@Manage Doperationparameter (name = "Financemic", description = "Financemic"), @ManagedOperationParameter (name = "Exclda            TE ", description =" Excldate "), @ManagedOperationParameter (name =" DayOfWeek ", description =" DayOfWeek "), @ManagedOperationParameter (name = "Excldesc", description = "Excldesc")}) public String inserttradedateexcl ( string financemic, int excldate, int dayOfWeek, String excldesc) {tradedateexcl tradedateexcl = new Tradedateexcl (        );        Tradedateexcl.setfinancemic (financemic);        Tradedateexcl.setexcldesc (EXCLDESC);        Tradedateexcl.setexcldate (excldate);        Tradedateexcl.setdayofweek (DayOfWeek); Boolean executeflag = Tradedateservice.inserttradedateexcl (tradedateexcl);        if (Executeflag) {return tradedatemonitormbean.ok_resp;        } else {return tradedatemonitormbean.fail_resp; }} @ManagedOperation (description = "Delete_trade_date_excl") @ManagedOperationParameters (value = {@M Anagedoperationparameter (name = "Financemic", description = "Financemic"), @ManagedOperationParameter (name = "E Xcldate ", description =" Excldate ")}) public String deletetradedateexcl (string financemic, int excldate) {T        Radedateexclkey Exclkey = new Tradedateexclkey ();        Exclkey.setexcldate (excldate);        Exclkey.setfinancemic (financemic);        Boolean executeflag = Tradedateservice.deletetradedateexcl (Exclkey);        if (Executeflag) {return tradedatemonitormbean.ok_resp;        } else {return tradedatemonitormbean.fail_resp; }    }}

JMX serviceurl Exposure

Package Com.jing.quote.server.config;import Org.apache.commons.logging.log;import Org.apache.commons.logging.logfactory;import Org.springframework.beans.factory.annotation.value;import Org.springframework.context.annotation.bean;import Org.springframework.context.annotation.configuration;import Org.springframework.context.annotation.dependson;import Org.springframework.jmx.support.connectorserverfactorybean;import Org.springframework.remoting.rmi.RmiRegistryFactoryBean; @Configurationpublic class Jmxautoconfiguration {private    Static final Log LOGGER = Logfactory.getlog (Jmxautoconfiguration.class);    @Value ("${jmx.rmi.host:localhost}") Private String rmihost;    @Value ("${jmx.rmi.port:9888}") Private Integer rmiport; @Bean public Rmiregistryfactorybean Rmiregistry () {//Specifies that the port can be opened to create a name service final Rmiregistryfactorybean Rmireg        Istryfactorybean = new Rmiregistryfactorybean ();        Rmiregistryfactorybean.setport (Rmiport); Rmiregistryfactorybean.setalwayscreAte (true);        Logger.info ("Rmiregistryfactorybean Create success!");    return Rmiregistryfactorybean;  } @Bean @DependsOn ("Rmiregistry") public Connectorserverfactorybean Connectorserverfactorybean () throws Exception        {Final Connectorserverfactorybean Connectorserverfactorybean = new Connectorserverfactorybean ();        Connectorserverfactorybean.setobjectname ("Connector:name=rmi"); Connectorserverfactorybean.setserviceurl (String.Format ("Service:jmx:rmi://%s:%s/jndi/rmi://%s:%s/jmxrmi",        Rmihost, Rmiport, Rmihost, Rmiport));        Logger.info ("Connectorserverfactorybean Create success!");    return Connectorserverfactorybean; }}

Jconsole access, direct remote connection to Service:jmx:rmi://localhost:9888/jndi/rmi://localhost:9888/jmxrmi (default)

Conclusion

Readers in this blog post, the proposed first according to the author of the above-mentioned literature link to consult JMX related knowledge points, combined with this article will have a certain understanding of the Springboot integrated JMX framework

Springboot sentiment edify-JMX analysis

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.