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.context.support; 018 019import org.springframework.beans.factory.BeanNameAware; 020import org.springframework.beans.factory.InitializingBean; 021import org.springframework.context.ApplicationContext; 022import org.springframework.lang.Nullable; 023import org.springframework.util.Assert; 024import org.springframework.util.StringUtils; 025 026/** 027 * {@link AbstractRefreshableApplicationContext} subclass that adds common handling 028 * of specified config locations. Serves as base class for XML-based application 029 * context implementations such as {@link ClassPathXmlApplicationContext} and 030 * {@link FileSystemXmlApplicationContext}, as well as 031 * {@link org.springframework.web.context.support.XmlWebApplicationContext}. 032 * 033 * @author Juergen Hoeller 034 * @since 2.5.2 035 * @see #setConfigLocation 036 * @see #setConfigLocations 037 * @see #getDefaultConfigLocations 038 */ 039public abstract class AbstractRefreshableConfigApplicationContext extends AbstractRefreshableApplicationContext 040 implements BeanNameAware, InitializingBean { 041 042 @Nullable 043 private String[] configLocations; 044 045 private boolean setIdCalled = false; 046 047 048 /** 049 * Create a new AbstractRefreshableConfigApplicationContext with no parent. 050 */ 051 public AbstractRefreshableConfigApplicationContext() { 052 } 053 054 /** 055 * Create a new AbstractRefreshableConfigApplicationContext with the given parent context. 056 * @param parent the parent context 057 */ 058 public AbstractRefreshableConfigApplicationContext(@Nullable ApplicationContext parent) { 059 super(parent); 060 } 061 062 063 /** 064 * Set the config locations for this application context in init-param style, 065 * i.e. with distinct locations separated by commas, semicolons or whitespace. 066 * <p>If not set, the implementation may use a default as appropriate. 067 */ 068 public void setConfigLocation(String location) { 069 setConfigLocations(StringUtils.tokenizeToStringArray(location, CONFIG_LOCATION_DELIMITERS)); 070 } 071 072 /** 073 * Set the config locations for this application context. 074 * <p>If not set, the implementation may use a default as appropriate. 075 */ 076 public void setConfigLocations(@Nullable String... locations) { 077 if (locations != null) { 078 Assert.noNullElements(locations, "Config locations must not be null"); 079 this.configLocations = new String[locations.length]; 080 for (int i = 0; i < locations.length; i++) { 081 this.configLocations[i] = resolvePath(locations[i]).trim(); 082 } 083 } 084 else { 085 this.configLocations = null; 086 } 087 } 088 089 /** 090 * Return an array of resource locations, referring to the XML bean definition 091 * files that this context should be built with. Can also include location 092 * patterns, which will get resolved via a ResourcePatternResolver. 093 * <p>The default implementation returns {@code null}. Subclasses can override 094 * this to provide a set of resource locations to load bean definitions from. 095 * @return an array of resource locations, or {@code null} if none 096 * @see #getResources 097 * @see #getResourcePatternResolver 098 */ 099 @Nullable 100 protected String[] getConfigLocations() { 101 return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations()); 102 } 103 104 /** 105 * Return the default config locations to use, for the case where no 106 * explicit config locations have been specified. 107 * <p>The default implementation returns {@code null}, 108 * requiring explicit config locations. 109 * @return an array of default config locations, if any 110 * @see #setConfigLocations 111 */ 112 @Nullable 113 protected String[] getDefaultConfigLocations() { 114 return null; 115 } 116 117 /** 118 * Resolve the given path, replacing placeholders with corresponding 119 * environment property values if necessary. Applied to config locations. 120 * @param path the original file path 121 * @return the resolved file path 122 * @see org.springframework.core.env.Environment#resolveRequiredPlaceholders(String) 123 */ 124 protected String resolvePath(String path) { 125 return getEnvironment().resolveRequiredPlaceholders(path); 126 } 127 128 129 @Override 130 public void setId(String id) { 131 super.setId(id); 132 this.setIdCalled = true; 133 } 134 135 /** 136 * Sets the id of this context to the bean name by default, 137 * for cases where the context instance is itself defined as a bean. 138 */ 139 @Override 140 public void setBeanName(String name) { 141 if (!this.setIdCalled) { 142 super.setId(name); 143 setDisplayName("ApplicationContext '" + name + "'"); 144 } 145 } 146 147 /** 148 * Triggers {@link #refresh()} if not refreshed in the concrete context's 149 * constructor already. 150 */ 151 @Override 152 public void afterPropertiesSet() { 153 if (!isActive()) { 154 refresh(); 155 } 156 } 157 158}