001/*
002 * Copyright 2002-2012 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 *      https://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.beans.factory.config;
018
019import org.apache.commons.logging.Log;
020import org.apache.commons.logging.LogFactory;
021
022import org.springframework.beans.BeansException;
023import org.springframework.beans.factory.BeanFactory;
024import org.springframework.util.ClassUtils;
025import org.springframework.util.StringUtils;
026
027/**
028 * Bean factory post processor that logs a warning for {@link Deprecated @Deprecated} beans.
029 *
030 * @author Arjen Poutsma
031 * @since 3.0.3
032 */
033public class DeprecatedBeanWarner implements BeanFactoryPostProcessor {
034
035        /**
036         * Logger available to subclasses.
037         */
038        protected transient Log logger = LogFactory.getLog(getClass());
039
040        /**
041         * Set the name of the logger to use.
042         * The name will be passed to the underlying logger implementation through Commons Logging,
043         * getting interpreted as log category according to the logger's configuration.
044         * <p>This can be specified to not log into the category of this warner class but rather
045         * into a specific named category.
046         * @see org.apache.commons.logging.LogFactory#getLog(String)
047         * @see org.apache.log4j.Logger#getLogger(String)
048         * @see java.util.logging.Logger#getLogger(String)
049         */
050        public void setLoggerName(String loggerName) {
051                this.logger = LogFactory.getLog(loggerName);
052        }
053
054
055        @Override
056        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
057                if (isLogEnabled()) {
058                        String[] beanNames = beanFactory.getBeanDefinitionNames();
059                        for (String beanName : beanNames) {
060                                String nameToLookup = beanName;
061                                if (beanFactory.isFactoryBean(beanName)) {
062                                        nameToLookup = BeanFactory.FACTORY_BEAN_PREFIX + beanName;
063                                }
064                                Class<?> beanType = ClassUtils.getUserClass(beanFactory.getType(nameToLookup));
065                                if (beanType != null && beanType.isAnnotationPresent(Deprecated.class)) {
066                                        BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
067                                        logDeprecatedBean(beanName, beanType, beanDefinition);
068                                }
069                        }
070                }
071        }
072
073        /**
074         * Logs a warning for a bean annotated with {@link Deprecated @Deprecated}.
075         * @param beanName the name of the deprecated bean
076         * @param beanType the user-specified type of the deprecated bean
077         * @param beanDefinition the definition of the deprecated bean
078         */
079        protected void logDeprecatedBean(String beanName, Class<?> beanType, BeanDefinition beanDefinition) {
080                StringBuilder builder = new StringBuilder();
081                builder.append(beanType);
082                builder.append(" ['");
083                builder.append(beanName);
084                builder.append('\'');
085                String resourceDescription = beanDefinition.getResourceDescription();
086                if (StringUtils.hasLength(resourceDescription)) {
087                        builder.append(" in ");
088                        builder.append(resourceDescription);
089                }
090                builder.append("] has been deprecated");
091                writeToLog(builder.toString());
092        }
093
094        /**
095         * Actually write to the underlying log.
096         * <p>The default implementations logs the message at "warn" level.
097         * @param message the message to write
098         */
099        protected void writeToLog(String message) {
100                logger.warn(message);
101        }
102
103        /**
104         * Determine whether the {@link #logger} field is enabled.
105         * <p>Default is {@code true} when the "warn" level is enabled.
106         * Subclasses can override this to change the level under which logging occurs.
107         */
108        protected boolean isLogEnabled() {
109                return logger.isWarnEnabled();
110        }
111
112}