001/*
002 * Copyright 2012-2018 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.context.EnvironmentAware;
030import org.springframework.context.annotation.Bean;
031import org.springframework.context.annotation.Configuration;
032import org.springframework.context.annotation.EnableMBeanExport;
033import org.springframework.context.annotation.MBeanExportConfiguration.SpecificPlatform;
034import org.springframework.context.annotation.Primary;
035import org.springframework.core.env.Environment;
036import org.springframework.jmx.export.MBeanExporter;
037import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource;
038import org.springframework.jmx.export.annotation.AnnotationMBeanExporter;
039import org.springframework.jmx.export.naming.ObjectNamingStrategy;
040import org.springframework.jmx.support.MBeanServerFactoryBean;
041import org.springframework.jmx.support.RegistrationPolicy;
042import org.springframework.util.StringUtils;
043
044/**
045 * {@link EnableAutoConfiguration Auto-configuration} to enable/disable Spring's
046 * {@link EnableMBeanExport} mechanism based on configuration properties.
047 * <p>
048 * To disable auto export of annotation beans set {@code spring.jmx.enabled: false}.
049 *
050 * @author Christian Dupuis
051 * @author Madhura Bhave
052 * @author Artsiom Yudovin
053 */
054@Configuration
055@ConditionalOnClass({ MBeanExporter.class })
056@ConditionalOnProperty(prefix = "spring.jmx", name = "enabled", havingValue = "true", matchIfMissing = true)
057public class JmxAutoConfiguration implements EnvironmentAware, BeanFactoryAware {
058
059        private Environment environment;
060
061        private BeanFactory beanFactory;
062
063        @Override
064        public void setEnvironment(Environment environment) {
065                this.environment = environment;
066        }
067
068        @Override
069        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
070                this.beanFactory = beanFactory;
071        }
072
073        @Bean
074        @Primary
075        @ConditionalOnMissingBean(value = MBeanExporter.class, search = SearchStrategy.CURRENT)
076        public AnnotationMBeanExporter mbeanExporter(ObjectNamingStrategy namingStrategy) {
077                AnnotationMBeanExporter exporter = new AnnotationMBeanExporter();
078                exporter.setRegistrationPolicy(RegistrationPolicy.FAIL_ON_EXISTING);
079                exporter.setNamingStrategy(namingStrategy);
080                String serverBean = this.environment.getProperty("spring.jmx.server",
081                                "mbeanServer");
082                if (StringUtils.hasLength(serverBean)) {
083                        exporter.setServer(this.beanFactory.getBean(serverBean, MBeanServer.class));
084                }
085                return exporter;
086        }
087
088        @Bean
089        @ConditionalOnMissingBean(value = ObjectNamingStrategy.class, search = SearchStrategy.CURRENT)
090        public ParentAwareNamingStrategy objectNamingStrategy() {
091                ParentAwareNamingStrategy namingStrategy = new ParentAwareNamingStrategy(
092                                new AnnotationJmxAttributeSource());
093                String defaultDomain = this.environment.getProperty("spring.jmx.default-domain");
094                if (StringUtils.hasLength(defaultDomain)) {
095                        namingStrategy.setDefaultDomain(defaultDomain);
096                }
097                boolean uniqueNames = this.environment.getProperty("spring.jmx.unique-names",
098                                Boolean.class, false);
099                namingStrategy.setEnsureUniqueRuntimeObjectNames(uniqueNames);
100                return namingStrategy;
101        }
102
103        @Bean
104        @ConditionalOnMissingBean
105        public MBeanServer mbeanServer() {
106                SpecificPlatform platform = SpecificPlatform.get();
107                if (platform != null) {
108                        return platform.getMBeanServer();
109                }
110                MBeanServerFactoryBean factory = new MBeanServerFactoryBean();
111                factory.setLocateExistingServerIfPossible(true);
112                factory.afterPropertiesSet();
113                return factory.getObject();
114        }
115
116}