001/* 002 * Copyright 2012-2015 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.autoconfigure.jmx; 018 019import javax.management.MBeanServer; 020 021import org.springframework.beans.BeansException; 022import org.springframework.beans.factory.BeanFactory; 023import org.springframework.beans.factory.BeanFactoryAware; 024import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 025import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 026import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 027import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 028import org.springframework.boot.autoconfigure.condition.SearchStrategy; 029import org.springframework.boot.bind.RelaxedPropertyResolver; 030import org.springframework.context.EnvironmentAware; 031import org.springframework.context.annotation.Bean; 032import org.springframework.context.annotation.Configuration; 033import org.springframework.context.annotation.EnableMBeanExport; 034import org.springframework.context.annotation.MBeanExportConfiguration.SpecificPlatform; 035import org.springframework.context.annotation.Primary; 036import org.springframework.core.env.Environment; 037import org.springframework.jmx.export.MBeanExporter; 038import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource; 039import org.springframework.jmx.export.annotation.AnnotationMBeanExporter; 040import org.springframework.jmx.export.naming.ObjectNamingStrategy; 041import org.springframework.jmx.support.MBeanServerFactoryBean; 042import org.springframework.jmx.support.RegistrationPolicy; 043import org.springframework.util.StringUtils; 044 045/** 046 * {@link EnableAutoConfiguration Auto-configuration} to enable/disable Spring's 047 * {@link EnableMBeanExport} mechanism based on configuration properties. 048 * <p> 049 * To disable auto export of annotation beans set {@code spring.jmx.enabled: false}. 050 * 051 * @author Christian Dupuis 052 */ 053@Configuration 054@ConditionalOnClass({ MBeanExporter.class }) 055@ConditionalOnProperty(prefix = "spring.jmx", name = "enabled", havingValue = "true", matchIfMissing = true) 056public class JmxAutoConfiguration implements EnvironmentAware, BeanFactoryAware { 057 058 private RelaxedPropertyResolver propertyResolver; 059 060 private BeanFactory beanFactory; 061 062 @Override 063 public void setEnvironment(Environment environment) { 064 this.propertyResolver = new RelaxedPropertyResolver(environment, "spring.jmx."); 065 } 066 067 @Override 068 public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 069 this.beanFactory = beanFactory; 070 } 071 072 @Bean 073 @Primary 074 @ConditionalOnMissingBean(value = MBeanExporter.class, search = SearchStrategy.CURRENT) 075 public AnnotationMBeanExporter mbeanExporter(ObjectNamingStrategy namingStrategy) { 076 AnnotationMBeanExporter exporter = new AnnotationMBeanExporter(); 077 exporter.setRegistrationPolicy(RegistrationPolicy.FAIL_ON_EXISTING); 078 exporter.setNamingStrategy(namingStrategy); 079 String server = this.propertyResolver.getProperty("server", "mbeanServer"); 080 if (StringUtils.hasLength(server)) { 081 exporter.setServer(this.beanFactory.getBean(server, MBeanServer.class)); 082 } 083 return exporter; 084 } 085 086 @Bean 087 @ConditionalOnMissingBean(value = ObjectNamingStrategy.class, search = SearchStrategy.CURRENT) 088 public ParentAwareNamingStrategy objectNamingStrategy() { 089 ParentAwareNamingStrategy namingStrategy = new ParentAwareNamingStrategy( 090 new AnnotationJmxAttributeSource()); 091 String defaultDomain = this.propertyResolver.getProperty("default-domain"); 092 if (StringUtils.hasLength(defaultDomain)) { 093 namingStrategy.setDefaultDomain(defaultDomain); 094 } 095 return namingStrategy; 096 } 097 098 @Bean 099 @ConditionalOnMissingBean(MBeanServer.class) 100 public MBeanServer mbeanServer() { 101 SpecificPlatform platform = SpecificPlatform.get(); 102 if (platform != null) { 103 return platform.getMBeanServer(); 104 } 105 MBeanServerFactoryBean factory = new MBeanServerFactoryBean(); 106 factory.setLocateExistingServerIfPossible(true); 107 factory.afterPropertiesSet(); 108 return factory.getObject(); 109 110 } 111 112}