Merge 3.1.0 development branch into trunk

Branch in question is 'env' branch from git://git.springsource.org/sandbox/cbeams.git; merged into
git-svn repository with:

    git merge -s recursive -Xtheirs --no-commit env

No merge conflicts, but did need to

    git rm spring-build

prior to committing.

With this change, Spring 3.1.0 development is now happening on SVN
trunk. Further commits to the 3.0.x line will happen in an as-yet
uncreated SVN branch.  3.1.0 snapshots will be available
per the usual nightly CI build from trunk.
This commit is contained in:
Chris Beams
2010-10-25 19:48:20 +00:00
parent b0ea2b13d2
commit f480333d31
211 changed files with 9876 additions and 623 deletions

View File

@@ -19,6 +19,7 @@ package org.springframework.context;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.support.ResourcePatternResolver;
/**
@@ -53,7 +54,7 @@ import org.springframework.core.io.support.ResourcePatternResolver;
* @see org.springframework.beans.factory.BeanFactory
* @see org.springframework.core.io.ResourceLoader
*/
public interface ApplicationContext extends ListableBeanFactory, HierarchicalBeanFactory,
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
/**

View File

@@ -19,6 +19,8 @@ package org.springframework.context;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
/**
* SPI interface to be implemented by most if not all application contexts.
@@ -31,6 +33,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
* methods should only be used by startup and shutdown code.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 03.11.2003
*/
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle {
@@ -59,6 +62,11 @@ public interface ConfigurableApplicationContext extends ApplicationContext, Life
*/
String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
/**
* Name of the {@link Environment} bean in the factory.
*/
String ENVIRONMENT_BEAN_NAME = "environment";
/**
* Name of the System properties bean in the factory.
* @see java.lang.System#getProperties()
@@ -87,6 +95,16 @@ public interface ConfigurableApplicationContext extends ApplicationContext, Life
*/
void setParent(ApplicationContext parent);
/**
* TODO SPR-7508: document
*/
ConfigurableEnvironment getEnvironment();
/**
* TODO SPR-7508: document
*/
void setEnvironment(ConfigurableEnvironment environment);
/**
* Add a new BeanFactoryPostProcessor that will get applied to the internal
* bean factory of this application context on refresh, before any of the
@@ -105,7 +123,7 @@ public interface ConfigurableApplicationContext extends ApplicationContext, Life
* @see org.springframework.context.event.ContextRefreshedEvent
* @see org.springframework.context.event.ContextClosedEvent
*/
void addApplicationListener(ApplicationListener listener);
void addApplicationListener(ApplicationListener<?> listener);
/**
* Load or refresh the persistent representation of the configuration,

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context;
import org.springframework.core.env.Environment;
/**
* TODO SPR-7515: document
*
* @author Chris Beams
*/
public interface EnvironmentAware {
void setEnvironment(Environment environment);
}

View File

@@ -24,6 +24,9 @@ import org.springframework.beans.factory.support.AutowireCandidateQualifier;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
/**
* Convenient adapter for programmatic registration of annotated bean classes.
@@ -31,6 +34,7 @@ import org.springframework.beans.factory.support.BeanNameGenerator;
* the same resolution of annotations but for explicitly registered classes only.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 3.0
* @see AnnotationConfigApplicationContext#register
*/
@@ -38,6 +42,8 @@ public class AnnotatedBeanDefinitionReader {
private final BeanDefinitionRegistry registry;
private Environment environment = new DefaultEnvironment();
private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
@@ -61,9 +67,17 @@ public class AnnotatedBeanDefinitionReader {
return this.registry;
}
/**
* Set the Environment to use when registering classes.
* <p>The default is a {@link DefaultEnvironment}.
*/
public void setEnvironment(Environment environment) {
this.environment = environment;
}
/**
* Set the BeanNameGenerator to use for detected bean classes.
* <p>Default is a {@link AnnotationBeanNameGenerator}.
* <p>The default is a {@link AnnotationBeanNameGenerator}.
*/
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
this.beanNameGenerator = (beanNameGenerator != null ? beanNameGenerator : new AnnotationBeanNameGenerator());
@@ -92,8 +106,45 @@ public class AnnotatedBeanDefinitionReader {
registerBean(annotatedClass, null, qualifiers);
}
private boolean hasEligibleProfile(AnnotationMetadata metadata) {
boolean hasEligibleProfile = false;
if (!metadata.hasAnnotation(Profile.class.getName())) {
hasEligibleProfile = true;
} else {
for (String profile : (String[])metadata.getAnnotationAttributes(Profile.class.getName()).get(Profile.CANDIDATE_PROFILES_ATTRIB_NAME)) {
if (this.environment.getActiveProfiles().contains(profile)) {
hasEligibleProfile = true;
break;
}
}
}
return hasEligibleProfile;
}
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (!hasEligibleProfile(abd.getMetadata())) {
// TODO SPR-7508: log that this bean is being rejected on profile mismatch
return;
}
/*
if (metadata.hasAnnotation(Profile.class.getName())) {
if (this.environment == null) {
return;
}
Map<String, Object> profileAttribs = metadata.getAnnotationAttributes(Profile.class.getName());
String[] names = (String[]) profileAttribs.get(Profile.CANDIDATE_PROFILES_ATTRIB_NAME);
boolean go=false;
for (String pName : names) {
if (this.environment.getActiveProfiles().contains(pName)) {
go = true;
}
}
if (!go) {
return;
}
}
*/
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

View File

@@ -16,8 +16,11 @@
package org.springframework.context.annotation;
import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
/**
* Standalone application context, accepting annotated classes as input - in particular
@@ -46,6 +49,9 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex
private final ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this);
{ // TODO: rework this, it's a bit confusing
this.setEnvironment(this.getEnvironment());
}
/**
* Create a new AnnotationConfigApplicationContext that needs to be populated
@@ -75,6 +81,15 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex
refresh();
}
/**
* TODO SPR-7508: document
*/
@Override
public void setEnvironment(ConfigurableEnvironment environment) {
super.setEnvironment(environment);
this.reader.setEnvironment(environment);
this.scanner.setEnvironment(environment);
}
/**
* Set the BeanNameGenerator to use for detected bean classes.
@@ -94,7 +109,6 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex
this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
}
/**
* Register an annotated class to be processed. Allows for programmatically
* building a {@link AnnotationConfigApplicationContext}. Note that

View File

@@ -39,7 +39,7 @@ import org.springframework.util.ClassUtils;
* @author Chris Beams
* @since 2.5
* @see CommonAnnotationBeanPostProcessor
* @see org.springframework.context.annotation.support.ConfigurationClassPostProcessor;
* @see org.springframework.context.annotation.ConfigurationClassPostProcessor
* @see org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
* @see org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
* @see org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor

View File

@@ -101,7 +101,7 @@ public @interface Bean {
* <p>Note: Only invoked on beans whose lifecycle is under the full control of the
* factory, which is always the case for singletons but not guaranteed
* for any other scope.
* @see {@link org.springframework.context.ConfigurableApplicationContext#close()}
* @see org.springframework.context.ConfigurableApplicationContext#close()
*/
String destroyMethod() default "";

View File

@@ -27,6 +27,7 @@ import org.springframework.beans.factory.support.BeanDefinitionDefaults;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.Assert;
import org.springframework.util.PatternMatchUtils;
@@ -48,6 +49,7 @@ import org.springframework.util.PatternMatchUtils;
*
* @author Mark Fisher
* @author Juergen Hoeller
* @author Chris Beams
* @since 2.5
* @see AnnotationConfigApplicationContext#scan
* @see org.springframework.stereotype.Component
@@ -87,6 +89,10 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
* {@link org.springframework.context.ApplicationContext} implementations.
* <p>If given a plain BeanDefinitionRegistry, the default ResourceLoader will be a
* {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver}.
* <p>If the the passed-in bean factory also implements {@link EnvironmentCapable} its
* environment will be used by this reader. Otherwise, the reader will initialize and
* use a {@link DefaultEnvironment}. All ApplicationContext implementations are
* EnvironmentCapable, while normal BeanFactory implementations are not.
* @param registry the BeanFactory to load bean definitions into,
* in the form of a BeanDefinitionRegistry
* @param useDefaultFilters whether to include the default filters for the
@@ -96,6 +102,7 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
* {@link org.springframework.stereotype.Controller @Controller} stereotype
* annotations.
* @see #setResourceLoader
* @see #setEnvironment
*/
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
super(useDefaultFilters);
@@ -107,6 +114,11 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
if (this.registry instanceof ResourceLoader) {
setResourceLoader((ResourceLoader) this.registry);
}
// Inherit Environment if possible
if (this.registry instanceof EnvironmentCapable) {
setEnvironment(((EnvironmentCapable) this.registry).getEnvironment());
}
}

View File

@@ -25,11 +25,13 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
@@ -46,7 +48,6 @@ import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.SystemPropertyUtils;
/**
* A component provider that scans the classpath from a base package. It then
@@ -59,18 +60,21 @@ import org.springframework.util.SystemPropertyUtils;
* @author Mark Fisher
* @author Juergen Hoeller
* @author Ramnivas Laddad
* @author Chris Beams
* @since 2.5
* @see org.springframework.core.type.classreading.MetadataReaderFactory
* @see org.springframework.core.type.AnnotationMetadata
* @see ScannedGenericBeanDefinition
*/
public class ClassPathScanningCandidateComponentProvider implements ResourceLoaderAware {
public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
private static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
protected final Log logger = LogFactory.getLog(getClass());
private Environment environment = new DefaultEnvironment();
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
@@ -110,6 +114,20 @@ public class ClassPathScanningCandidateComponentProvider implements ResourceLoad
this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
}
/**
* TODO SPR-7508: document
*/
public void setEnvironment(Environment environment) {
this.environment = environment;
}
/**
* TODO SPR-7508: document
*/
public Environment getEnvironment() {
return this.environment;
}
/**
* Return the ResourceLoader that this component provider uses.
*/
@@ -261,7 +279,7 @@ public class ClassPathScanningCandidateComponentProvider implements ResourceLoad
* @return the pattern specification to be used for package searching
*/
protected String resolveBasePackage(String basePackage) {
return ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(basePackage));
return ClassUtils.convertClassNameToResourcePath(environment.resolveRequiredPlaceholders(basePackage));
}
/**
@@ -278,12 +296,28 @@ public class ClassPathScanningCandidateComponentProvider implements ResourceLoad
}
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, this.metadataReaderFactory)) {
return true;
return hasEligibleProfile(metadataReader);
}
}
return false;
}
private boolean hasEligibleProfile(MetadataReader metadataReader) {
boolean hasEligibleProfile = false;
if (!metadataReader.getAnnotationMetadata().hasAnnotation(Profile.class.getName())) {
hasEligibleProfile = true;
} else {
for (String profile : (String[])metadataReader.getAnnotationMetadata().getAnnotationAttributes(Profile.class.getName()).get(Profile.CANDIDATE_PROFILES_ATTRIB_NAME)) {
if (this.environment.getActiveProfiles().contains(profile)) {
hasEligibleProfile = true;
break;
}
}
}
return hasEligibleProfile;
}
/**
* Determine whether the given bean definition qualifies as candidate.
* <p>The default implementation checks whether the class is concrete

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.support.BeanNameGenerator;
/**
* Configures component scanning directives for use with {@link Configuration}
* classes. Provides support parallel with Spring XML's
* &lt;context:component-scan&gt; element.
*
* TODO SPR-7508: complete documentation.
*
* @author Chris Beams
* @since 3.1
* @see FilterType
* @see Configuration
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
/** base packages to scan */
String[] value() default {};
Class<?>[] packageOf() default Void.class;
Class<? extends BeanNameGenerator> nameGenerator() default AnnotationBeanNameGenerator.class;
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
String resourcePattern() default "**/*.class";
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
boolean useDefaultFilters() default true;
IncludeFilter[] includeFilters() default {};
ExcludeFilter[] excludeFilters() default {};
@Retention(RetentionPolicy.SOURCE)
@interface IncludeFilter {
FilterType type() default FilterType.ANNOTATION;
Class<?> value();
}
@Retention(RetentionPolicy.SOURCE)
@interface ExcludeFilter {
FilterType type() default FilterType.ANNOTATION;
Class<?> value();
}
}

View File

@@ -98,6 +98,7 @@ public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser {
// Delegate bean definition registration to scanner class.
ClassPathBeanDefinitionScanner scanner = createScanner(readerContext, useDefaultFilters);
scanner.setResourceLoader(readerContext.getResourceLoader());
scanner.setEnvironment(parserContext.getDelegate().getEnvironment());
scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());
scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());

View File

@@ -57,6 +57,7 @@ import org.springframework.stereotype.Component;
* @see Bean
* @see ConfigurationClassPostProcessor
* @see AnnotationConfigApplicationContext
* @see org.springframework.context.annotation.Profile
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -105,7 +105,6 @@ final class ConfigurationClass {
return this.importedResources;
}
public void validate(ProblemReporter problemReporter) {
// An @Bean method may only be overloaded through inheritance. No single
// @Configuration class may declare two @Bean methods with the same name.

View File

@@ -27,6 +27,7 @@ import java.util.Stack;
import org.springframework.beans.factory.parsing.Location;
import org.springframework.beans.factory.parsing.Problem;
import org.springframework.beans.factory.parsing.ProblemReporter;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.StandardAnnotationMetadata;
@@ -63,14 +64,18 @@ class ConfigurationClassParser {
private final Set<ConfigurationClass> configurationClasses =
new LinkedHashSet<ConfigurationClass>();
private final Environment environment;
/**
* Create a new {@link ConfigurationClassParser} instance that will be used
* to populate the set of configuration classes.
*/
public ConfigurationClassParser(MetadataReaderFactory metadataReaderFactory, ProblemReporter problemReporter) {
public ConfigurationClassParser(MetadataReaderFactory metadataReaderFactory,
ProblemReporter problemReporter, Environment environment) {
this.metadataReaderFactory = metadataReaderFactory;
this.problemReporter = problemReporter;
this.environment = environment;
}
@@ -95,8 +100,28 @@ class ConfigurationClassParser {
processConfigurationClass(new ConfigurationClass(clazz, beanName));
}
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
boolean hasEligibleProfile = false;
if (this.environment == null) {
hasEligibleProfile = true;
} else {
if (!configClass.getMetadata().hasAnnotation(Profile.class.getName())) {
hasEligibleProfile = true;
} else {
for (String profile : (String[])configClass.getMetadata().getAnnotationAttributes(Profile.class.getName()).get(Profile.CANDIDATE_PROFILES_ATTRIB_NAME)) {
if (this.environment.getActiveProfiles().contains(profile)) {
hasEligibleProfile = true;
break;
}
}
}
}
if (!hasEligibleProfile) {
//logger.debug("TODO SPR-7508: issue debug statement that this class is being excluded");
// make sure XML has a symmetrical statement as well
return;
}
AnnotationMetadata metadata = configClass.getMetadata();
while (metadata != null) {
doProcessConfigurationClass(configClass, metadata);
@@ -120,6 +145,7 @@ class ConfigurationClassParser {
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
}
this.configurationClasses.add(configClass);
}

View File

@@ -16,6 +16,7 @@
package org.springframework.context.annotation;
import java.awt.dnd.Autoscroll;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@@ -38,7 +39,9 @@ import org.springframework.beans.factory.parsing.SourceExtractor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.Ordered;
import org.springframework.core.env.Environment;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.Assert;
@@ -61,7 +64,8 @@ import org.springframework.util.ClassUtils;
* @author Juergen Hoeller
* @since 3.0
*/
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, BeanClassLoaderAware {
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
BeanClassLoaderAware, EnvironmentAware {
/** Whether the CGLIB2 library is present on the classpath */
private static final boolean cglibAvailable = ClassUtils.isPresent(
@@ -84,6 +88,8 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
private boolean postProcessBeanFactoryCalled = false;
private Environment environment;
/**
* Set the {@link SourceExtractor} to use for generated bean definitions
@@ -121,8 +127,12 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
}
}
public void setEnvironment(Environment environment) {
this.environment = environment;
}
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
return Ordered.HIGHEST_PRECEDENCE + 1; // make room for AutoScanningBeanDefinitionRegistrar
}
@@ -180,7 +190,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
}
// Populate a new configuration model by parsing each @Configuration classes
ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter);
ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment);
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,19 +16,39 @@
package org.springframework.context.annotation;
import org.springframework.core.type.filter.AssignableTypeFilter;
/**
* Enumeration of the valid type filters to be added for annotation-driven configuration.
* Enumeration of the type filters that may be used in conjunction with
* {@link ComponentScan @ComponentScan}.
*
* @author Mark Fisher
* @author Juergen Hoeller
* @author Chris Beams
* @since 2.5
* @see ComponentScan
* @see ComponentScan.IncludeFilter
* @see ComponentScan.ExcludeFilter
* @see org.springframework.core.type.filter.TypeFilter
*/
public enum FilterType {
/**
* Filter candidates marked with a given annotation.
* @see org.springframework.core.type.filter.AnnotationTypeFilter
*/
ANNOTATION,
/**
* Filter candidates assignable to a given type.
* @see AssignableTypeFilter
*/
ASSIGNABLE_TYPE,
ASPECTJ_PATTERN,
REGEX_PATTERN,
/** Filter candidates using a given custom
* {@link org.springframework.core.type.filter.TypeFilter} implementation
*/
CUSTOM
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Chris Beams
* @since 3.1
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({
ANNOTATION_TYPE, // @Profile may be used as a meta-annotation
TYPE // In conjunction with @Component and its derivatives
})
public @interface Profile {
/**
* @see #value()
*/
static final String CANDIDATE_PROFILES_ATTRIB_NAME = "value";
/**
* TODO SPR-7508: document
*/
String[] value();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import org.w3c.dom.Element;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.support.EnvironmentAwarePropertyPlaceholderConfigurer;
import org.springframework.util.StringUtils;
/**
@@ -27,15 +28,24 @@ import org.springframework.util.StringUtils;
*
* @author Juergen Hoeller
* @author Dave Syer
* @author Chris Beams
* @since 2.5
*/
class PropertyPlaceholderBeanDefinitionParser extends AbstractPropertyLoadingBeanDefinitionParser {
@Override
protected Class getBeanClass(Element element) {
return PropertyPlaceholderConfigurer.class;
protected Class<?> getBeanClass(Element element) {
// as of Spring 3.1, the default for system-properties-mode is DELEGATE,
// meaning that the attribute should be disregarded entirely, instead
// deferring to the order of PropertySource objects in the enclosing
// application context's Environment object
if (!"DELEGATE".equals(element.getAttribute("system-properties-mode"))) {
return PropertyPlaceholderConfigurer.class;
}
return EnvironmentAwarePropertyPlaceholderConfigurer.class;
}
@Override
protected void doParse(Element element, BeanDefinitionBuilder builder) {
@@ -44,9 +54,11 @@ class PropertyPlaceholderBeanDefinitionParser extends AbstractPropertyLoadingBea
builder.addPropertyValue("ignoreUnresolvablePlaceholders",
Boolean.valueOf(element.getAttribute("ignore-unresolvable")));
String systemPropertiesModeName = element.getAttribute("system-properties-mode");
if (StringUtils.hasLength(systemPropertiesModeName)) {
builder.addPropertyValue("systemPropertiesModeName", "SYSTEM_PROPERTIES_MODE_"+systemPropertiesModeName);
if (!"DELEGATE".equals(element.getAttribute("system-properties-mode"))) {
String systemPropertiesModeName = element.getAttribute("system-properties-mode");
if (StringUtils.hasLength(systemPropertiesModeName)) {
builder.addPropertyValue("systemPropertiesModeName", "SYSTEM_PROPERTIES_MODE_"+systemPropertiesModeName);
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.expression;
import org.springframework.core.env.Environment;
import org.springframework.expression.AccessException;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.TypedValue;
/**
* Read-only EL property accessor that knows how to retrieve keys
* of a Spring {@link Environment} instance.
*
* @author Chris Beams
* @since 3.1
*/
public class EnvironmentAccessor implements PropertyAccessor {
public Class<?>[] getSpecificTargetClasses() {
return new Class[] { Environment.class };
}
/**
* Can read any {@link Environment}, thus always returns true.
* @return true
*/
public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
return true;
}
/**
* Access provided {@literal target} object by calling its {@link Environment#getProperty(String)}
* method with the provided {@literal name}.
*/
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
return new TypedValue(((Environment)target).getProperty(name));
}
/**
* Read only.
* @return false
*/
public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
return false;
}
/**
* Read only. No-op.
*/
public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException {
}
}

View File

@@ -126,6 +126,7 @@ public class StandardBeanExpressionResolver implements BeanExpressionResolver {
sec.addPropertyAccessor(new BeanExpressionContextAccessor());
sec.addPropertyAccessor(new BeanFactoryAccessor());
sec.addPropertyAccessor(new MapAccessor());
sec.addPropertyAccessor(new EnvironmentAccessor());
sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory()));
sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader()));
ConversionService conversionService = evalContext.getBeanFactory().getConversionService();

View File

@@ -18,7 +18,6 @@ package org.springframework.context.support;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -33,7 +32,6 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.DisposableBean;
@@ -54,6 +52,7 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.HierarchicalMessageSource;
import org.springframework.context.LifecycleProcessor;
import org.springframework.context.MessageSource;
@@ -73,6 +72,8 @@ import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
@@ -203,7 +204,10 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
private ApplicationEventMulticaster applicationEventMulticaster;
/** Statically specified listeners */
private Set<ApplicationListener> applicationListeners = new LinkedHashSet<ApplicationListener>();
private Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<ApplicationListener<?>>();
/** TODO SPR-7508: document */
private ConfigurableEnvironment environment = new DefaultEnvironment();
/**
@@ -271,6 +275,14 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
return this.parent;
}
public ConfigurableEnvironment getEnvironment() {
return this.environment;
}
public void setEnvironment(ConfigurableEnvironment environment) {
this.environment = environment;
}
/**
* Return this context's internal bean factory as AutowireCapableBeanFactory,
* if already available.
@@ -363,6 +375,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
this.beanFactoryPostProcessors.add(beanFactoryPostProcessor);
}
/**
* Return the list of BeanFactoryPostProcessors that will get applied
* to the internal BeanFactory.
@@ -371,7 +384,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
return this.beanFactoryPostProcessors;
}
public void addApplicationListener(ApplicationListener listener) {
public void addApplicationListener(ApplicationListener<?> listener) {
if (this.applicationEventMulticaster != null) {
this.applicationEventMulticaster.addApplicationListener(listener);
}
@@ -383,7 +396,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
/**
* Return the list of statically specified ApplicationListeners.
*/
public Collection<ApplicationListener> getApplicationListeners() {
public Collection<ApplicationListener<?>> getApplicationListeners() {
return this.applicationListeners;
}
@@ -481,7 +494,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
@@ -489,6 +502,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
@@ -505,54 +519,16 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
}
// Register default environment beans.
if (!beanFactory.containsBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
Map systemProperties;
try {
systemProperties = System.getProperties();
}
catch (AccessControlException ex) {
systemProperties = new ReadOnlySystemAttributesMap() {
@Override
protected String getSystemAttribute(String propertyName) {
try {
return System.getProperty(propertyName);
}
catch (AccessControlException ex) {
if (logger.isInfoEnabled()) {
logger.info("Not allowed to obtain system property [" + propertyName + "]: " +
ex.getMessage());
}
return null;
}
}
};
}
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, systemProperties);
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
Map<String,String> systemEnvironment;
try {
systemEnvironment = System.getenv();
}
catch (AccessControlException ex) {
systemEnvironment = new ReadOnlySystemAttributesMap() {
@Override
protected String getSystemAttribute(String variableName) {
try {
return System.getenv(variableName);
}
catch (AccessControlException ex) {
if (logger.isInfoEnabled()) {
logger.info("Not allowed to obtain system environment variable [" + variableName + "]: " +
ex.getMessage());
}
return null;
}
}
};
}
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, systemEnvironment);
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
@@ -664,6 +640,15 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
}
}
/**
* Common location for subclasses to call and receive registration of standard
* {@link BeanFactoryPostProcessor} bean definitions.
*
* @param registry subclass BeanDefinitionRegistry
*/
protected void registerStandardBeanFactoryPostProcessors(BeanDefinitionRegistry registry) {
}
/**
* Instantiate and invoke all registered BeanPostProcessor beans,
* respecting explicit order if given.
@@ -848,7 +833,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
*/
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener listener : getApplicationListeners()) {
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
@@ -869,7 +854,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
* @deprecated as of Spring 3.0, in favor of {@link #addApplicationListener}
*/
@Deprecated
protected void addListener(ApplicationListener listener) {
protected void addListener(ApplicationListener<?> listener) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
@@ -1099,7 +1084,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
return getBeanFactory().isPrototype(name);
}
public boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException {
public boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException {
return getBeanFactory().isTypeMatch(name, targetType);
}
@@ -1128,11 +1113,11 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
return getBeanFactory().getBeanDefinitionNames();
}
public String[] getBeanNamesForType(Class type) {
public String[] getBeanNamesForType(Class<?> type) {
return getBeanFactory().getBeanNamesForType(type);
}
public String[] getBeanNamesForType(Class type, boolean includeNonSingletons, boolean allowEagerInit) {
public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
return getBeanFactory().getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
}
@@ -1347,7 +1332,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
private final Map<String, Boolean> singletonNames = new ConcurrentHashMap<String, Boolean>();
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) {
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if (beanDefinition.isSingleton()) {
this.singletonNames.put(beanName, Boolean.TRUE);
}
@@ -1363,7 +1348,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
Boolean flag = this.singletonNames.get(beanName);
if (Boolean.TRUE.equals(flag)) {
// singleton bean (top-level or inner): register on the fly
addApplicationListener((ApplicationListener) bean);
addApplicationListener((ApplicationListener<?>) bean);
}
else if (flag == null) {
if (logger.isWarnEnabled() && !containsBean(beanName)) {

View File

@@ -53,6 +53,7 @@ import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
* supports {@literal @Configuration}-annotated classes as a source of bean definitions.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 1.1.3
* @see #loadBeanDefinitions
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory
@@ -217,6 +218,7 @@ public abstract class AbstractRefreshableApplicationContext extends AbstractAppl
}
beanFactory.setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer());
beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
registerStandardBeanFactoryPostProcessors(beanFactory);
}
/**

View File

@@ -117,9 +117,13 @@ public abstract class AbstractRefreshableConfigApplicationContext extends Abstra
* system property values if necessary. Applied to config locations.
* @param path the original file path
* @return the resolved file path
* @see org.springframework.util.SystemPropertyUtils#resolvePlaceholders
* @see SystemPropertyUtils#resolveRequiredPlaceholders(String)
*/
protected String resolvePath(String path) {
// TODO SPR-7508: note that ARAC cannot delegate to its beanFactory's environment
// to call Environment.resolve[Required]Placeholders(String), as the bean factory
// has not yet been initialized. This amounts to one more reason not to use the ARAC
// hierarchy - it won't have early access to environment property resolution.
return SystemPropertyUtils.resolvePlaceholders(path);
}

View File

@@ -83,6 +83,7 @@ public abstract class AbstractXmlApplicationContext extends AbstractRefreshableC
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

View File

@@ -27,8 +27,10 @@ import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.env.Environment;
import org.springframework.util.StringValueResolver;
/**
@@ -37,18 +39,24 @@ import org.springframework.util.StringValueResolver;
* implement the {@link ResourceLoaderAware}, {@link MessageSourceAware},
* {@link ApplicationEventPublisherAware} and/or
* {@link ApplicationContextAware} interfaces.
* If all of them are implemented, they are satisfied in the given order.
*
* <p>Also delegates the ApplicationContext {@link Environment} instance
* to beans that implement {@link EnvironmentAware}.
*
* <p>Implemented interfaces are satisfied in order of their mention above.
*
* <p>Application contexts will automatically register this with their
* underlying bean factory. Applications do not use this directly.
*
* @author Juergen Hoeller
* @author Costin Leau
* @author Chris Beams
* @since 10.10.2003
* @see org.springframework.context.ResourceLoaderAware
* @see org.springframework.context.MessageSourceAware
* @see org.springframework.context.ApplicationEventPublisherAware
* @see org.springframework.context.ApplicationContextAware
* @see org.springframework.context.EnvironmentAware
* @see org.springframework.context.support.AbstractApplicationContext#refresh()
*/
class ApplicationContextAwareProcessor implements BeanPostProcessor {
@@ -105,6 +113,9 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
}
public Object postProcessAfterInitialization(Object bean, String beanName) {

View File

@@ -0,0 +1,115 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.support;
import java.util.LinkedList;
import java.util.Properties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AbstractPropertyPlaceholderConfigurer;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.util.Assert;
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
/**
* TODO SPR-7508: document
*
* Local properties are added as a property source in any case. Precedence is based
* on the value of the {@link #setLocalOverride(boolean) localOverride} property.
*
* @author Chris Beams
* @since 3.1
* @see PropertyPlaceholderConfigurer
* @see EnvironmentAwarePropertyOverrideConfigurer
*/
public class EnvironmentAwarePropertyPlaceholderConfigurer
extends AbstractPropertyPlaceholderConfigurer implements EnvironmentAware {
private ConfigurableEnvironment environment;
private Environment wrappedEnvironment;
public void setEnvironment(Environment environment) {
this.wrappedEnvironment = environment;
}
@Override
protected PlaceholderResolver getPlaceholderResolver(Properties props) {
return new PlaceholderResolver() {
public String resolvePlaceholder(String placeholderName) {
return environment.getProperty(placeholderName);
}
};
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Assert.notNull(this.wrappedEnvironment, "Environment must not be null. Did you call setEnvironment()?");
environment = new AbstractEnvironment() { };
LinkedList<PropertySource<?>> propertySources = environment.getPropertySources();
EnvironmentPropertySource environmentPropertySource =
new EnvironmentPropertySource("wrappedEnvironment", wrappedEnvironment);
if (!this.localOverride) {
propertySources.add(environmentPropertySource);
}
if (this.localProperties != null) {
int cx=0;
for (Properties localProps : this.localProperties) {
propertySources.add(new PropertiesPropertySource("localProperties"+cx++, localProps));
}
}
if (this.localOverride) {
propertySources.add(environmentPropertySource);
}
super.postProcessBeanFactory(beanFactory);
}
static class EnvironmentPropertySource extends PropertySource<Environment> {
public EnvironmentPropertySource(String name, Environment source) {
super(name, source);
}
@Override
public boolean containsProperty(String key) {
return source.containsProperty(key);
}
@Override
public String getProperty(String key) {
return source.getProperty(key);
}
@Override
public int size() {
// TODO Auto-generated method stub
return source.getPropertyCount();
}
}
}

View File

@@ -28,6 +28,7 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
@@ -78,6 +79,7 @@ import org.springframework.util.Assert;
* from the {@link AbstractRefreshableApplicationContext} base class.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 1.1.2
* @see #registerBeanDefinition
* @see #refresh()
@@ -102,6 +104,7 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
this.beanFactory = new DefaultListableBeanFactory();
this.beanFactory.setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer());
this.beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
registerStandardBeanFactoryPostProcessors(this.beanFactory);
}
/**
@@ -181,7 +184,7 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
* delegate all <code>getResource</code> calls to the given ResourceLoader.
* If not set, default resource loading will apply.
* <p>The main reason to specify a custom ResourceLoader is to resolve
* resource paths (withour URL prefix) in a specific fashion.
* resource paths (without URL prefix) in a specific fashion.
* The default behavior is to resolve such paths as class path locations.
* To resolve resource paths as file system locations, specify a
* FileSystemResourceLoader here.

View File

@@ -17,7 +17,7 @@
package org.springframework.context.support;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.Resource;
/**
@@ -47,6 +47,7 @@ public class GenericXmlApplicationContext extends GenericApplicationContext {
* through {@link #load} calls and then manually {@link #refresh refreshed}.
*/
public GenericXmlApplicationContext() {
reader.setEnvironment(this.getEnvironment());
}
/**
@@ -88,6 +89,15 @@ public class GenericXmlApplicationContext extends GenericApplicationContext {
this.reader.setValidating(validating);
}
/**
* Set a custom environment. Should be called before any call to
* {@link #load}. TODO SPR-7508: document
*/
@Override
public void setEnvironment(ConfigurableEnvironment environment) {
super.setEnvironment(environment);
this.reader.setEnvironment(this.getEnvironment());
}
/**
* Load bean definitions from the given XML resources.

View File

@@ -1,98 +0,0 @@
/*
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.support;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
/**
* Read-only {@code Map<String, String>} implementation that is backed by system properties or environment
* variables.
*
* <p>Used by {@link AbstractApplicationContext} when a {@link SecurityManager} prohibits access to {@link
* System#getProperties()} or {@link System#getenv()}.
*
* @author Arjen Poutsma
* @since 3.0
*/
abstract class ReadOnlySystemAttributesMap implements Map<String, String> {
public boolean containsKey(Object key) {
return get(key) != null;
}
public String get(Object key) {
if (key instanceof String) {
String attributeName = (String) key;
return getSystemAttribute(attributeName);
}
else {
return null;
}
}
public boolean isEmpty() {
return false;
}
/**
* Template method that returns the underlying system attribute.
*
* <p>Implementations typically call {@link System#getProperty(String)} or {@link System#getenv(String)} here.
*/
protected abstract String getSystemAttribute(String attributeName);
// Unsupported
public int size() {
throw new UnsupportedOperationException();
}
public String put(String key, String value) {
throw new UnsupportedOperationException();
}
public boolean containsValue(Object value) {
throw new UnsupportedOperationException();
}
public String remove(Object key) {
throw new UnsupportedOperationException();
}
public void clear() {
throw new UnsupportedOperationException();
}
public Set<String> keySet() {
throw new UnsupportedOperationException();
}
public void putAll(Map<? extends String, ? extends String> m) {
throw new UnsupportedOperationException();
}
public Collection<String> values() {
throw new UnsupportedOperationException();
}
public Set<Entry<String, String>> entrySet() {
throw new UnsupportedOperationException();
}
}

View File

@@ -21,6 +21,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
@@ -29,6 +30,8 @@ import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.jndi.JndiLocatorSupport;
import org.springframework.jndi.TypeMismatchNamingException;
@@ -67,6 +70,9 @@ public class SimpleJndiBeanFactory extends JndiLocatorSupport implements BeanFac
/** Cache of the types of nonshareable resources: bean name --> bean type */
private final Map<String, Class> resourceTypes = new HashMap<String, Class>();
/** TODO SPR-7508: should be JNDI-specific environment */
private ConfigurableEnvironment environment = new DefaultEnvironment();
public SimpleJndiBeanFactory() {
setResourceRef(true);
@@ -94,6 +100,11 @@ public class SimpleJndiBeanFactory extends JndiLocatorSupport implements BeanFac
}
//---------------------------------------------------------------------
// Implementation of BeanFactory interface
//---------------------------------------------------------------------
public Object getBean(String name) throws BeansException {
return getBean(name, Object.class);
}