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}