001/*
002 * Copyright 2002-2017 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 java.io.IOException;
020import java.util.Properties;
021
022import org.springframework.beans.factory.FactoryBean;
023import org.springframework.beans.factory.InitializingBean;
024import org.springframework.core.io.support.PropertiesLoaderSupport;
025import org.springframework.lang.Nullable;
026
027/**
028 * Allows for making a properties file from a classpath location available
029 * as Properties instance in a bean factory. Can be used to populate
030 * any bean property of type Properties via a bean reference.
031 *
032 * <p>Supports loading from a properties file and/or setting local properties
033 * on this FactoryBean. The created Properties instance will be merged from
034 * loaded and local values. If neither a location nor local properties are set,
035 * an exception will be thrown on initialization.
036 *
037 * <p>Can create a singleton or a new object on each request.
038 * Default is a singleton.
039 *
040 * @author Juergen Hoeller
041 * @see #setLocation
042 * @see #setProperties
043 * @see #setLocalOverride
044 * @see java.util.Properties
045 */
046public class PropertiesFactoryBean extends PropertiesLoaderSupport
047                implements FactoryBean<Properties>, InitializingBean {
048
049        private boolean singleton = true;
050
051        @Nullable
052        private Properties singletonInstance;
053
054
055        /**
056         * Set whether a shared 'singleton' Properties instance should be
057         * created, or rather a new Properties instance on each request.
058         * <p>Default is "true" (a shared singleton).
059         */
060        public final void setSingleton(boolean singleton) {
061                this.singleton = singleton;
062        }
063
064        @Override
065        public final boolean isSingleton() {
066                return this.singleton;
067        }
068
069
070        @Override
071        public final void afterPropertiesSet() throws IOException {
072                if (this.singleton) {
073                        this.singletonInstance = createProperties();
074                }
075        }
076
077        @Override
078        @Nullable
079        public final Properties getObject() throws IOException {
080                if (this.singleton) {
081                        return this.singletonInstance;
082                }
083                else {
084                        return createProperties();
085                }
086        }
087
088        @Override
089        public Class<Properties> getObjectType() {
090                return Properties.class;
091        }
092
093
094        /**
095         * Template method that subclasses may override to construct the object
096         * returned by this factory. The default implementation returns the
097         * plain merged Properties instance.
098         * <p>Invoked on initialization of this FactoryBean in case of a
099         * shared singleton; else, on each {@link #getObject()} call.
100         * @return the object returned by this factory
101         * @throws IOException if an exception occurred during properties loading
102         * @see #mergeProperties()
103         */
104        protected Properties createProperties() throws IOException {
105                return mergeProperties();
106        }
107
108}