reworked ConfigurationClass(Web)ApplicationContext into AnnotationConfig(Web)ApplicationContext; revised BeansException signatures
This commit is contained in:
@@ -27,10 +27,12 @@ import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
|
||||
/**
|
||||
* Convenient adapter for programmatic registration of annotated bean classes.
|
||||
*
|
||||
* This is an alternative to {@link ClassPathBeanDefinitionScanner}, applying
|
||||
* the same resolution of annotations but for explicitly registered classes only.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see AnnotationConfigApplicationContext#register
|
||||
*/
|
||||
public class AnnotatedBeanDefinitionReader {
|
||||
|
||||
@@ -40,11 +42,15 @@ public class AnnotatedBeanDefinitionReader {
|
||||
|
||||
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
|
||||
|
||||
private boolean includeAnnotationConfig = true;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new AnnotatedBeanDefinitionReader for the given bean factory.
|
||||
* @param registry the BeanFactory to load bean definitions into,
|
||||
* in the form of a BeanDefinitionRegistry
|
||||
*/
|
||||
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
|
||||
this.registry = registry;
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
|
||||
}
|
||||
|
||||
|
||||
@@ -65,35 +71,14 @@ public class AnnotatedBeanDefinitionReader {
|
||||
|
||||
/**
|
||||
* Set the ScopeMetadataResolver to use for detected bean classes.
|
||||
* Note that this will override any custom "scopedProxyMode" setting.
|
||||
* <p>The default is an {@link AnnotationScopeMetadataResolver}.
|
||||
* @see #setScopedProxyMode
|
||||
*/
|
||||
public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
|
||||
this.scopeMetadataResolver = scopeMetadataResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the proxy behavior for non-singleton scoped beans.
|
||||
* Note that this will override any custom "scopeMetadataResolver" setting.
|
||||
* <p>The default is {@link ScopedProxyMode#NO}.
|
||||
* @see #setScopeMetadataResolver
|
||||
*/
|
||||
public void setScopedProxyMode(ScopedProxyMode scopedProxyMode) {
|
||||
this.scopeMetadataResolver = new AnnotationScopeMetadataResolver(scopedProxyMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether to register annotation config post-processors.
|
||||
* <p>The default is to register the post-processors. Turn this off
|
||||
* to be able to ignore the annotations or to process them differently.
|
||||
*/
|
||||
public void setIncludeAnnotationConfig(boolean includeAnnotationConfig) {
|
||||
this.includeAnnotationConfig = includeAnnotationConfig;
|
||||
this.scopeMetadataResolver = (scopeMetadataResolver != null ? scopeMetadataResolver : new AnnotationScopeMetadataResolver());
|
||||
}
|
||||
|
||||
|
||||
public void registerBeans(Class<?>... annotatedClasses) {
|
||||
public void register(Class<?>... annotatedClasses) {
|
||||
for (Class<?> annotatedClass : annotatedClasses) {
|
||||
registerBean(annotatedClass);
|
||||
}
|
||||
@@ -112,17 +97,7 @@ public class AnnotatedBeanDefinitionReader {
|
||||
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
|
||||
abd.setScope(scopeMetadata.getScopeName());
|
||||
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
|
||||
if (abd.getMetadata().isAnnotated(Primary.class.getName())) {
|
||||
abd.setPrimary(true);
|
||||
}
|
||||
if (abd.getMetadata().isAnnotated(Lazy.class.getName())) {
|
||||
Boolean value = (Boolean) abd.getMetadata().getAnnotationAttributes(Lazy.class.getName()).get("value");
|
||||
abd.setLazyInit(value);
|
||||
}
|
||||
if (abd.getMetadata().isAnnotated(DependsOn.class.getName())) {
|
||||
String[] value = (String[]) abd.getMetadata().getAnnotationAttributes(DependsOn.class.getName()).get("value");
|
||||
abd.setDependsOn(value);
|
||||
}
|
||||
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
|
||||
if (qualifiers != null) {
|
||||
for (Class<? extends Annotation> qualifier : qualifiers) {
|
||||
if (Primary.class.equals(qualifier)) {
|
||||
@@ -137,28 +112,8 @@ public class AnnotatedBeanDefinitionReader {
|
||||
}
|
||||
}
|
||||
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
|
||||
definitionHolder = applyScopedProxyMode(definitionHolder, scopeMetadata);
|
||||
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
|
||||
|
||||
// Register annotation config processors, if necessary.
|
||||
if (this.includeAnnotationConfig) {
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the specified scope to the given bean definition.
|
||||
* @param definition the bean definition to configure
|
||||
* @param metadata the corresponding scope metadata
|
||||
* @return the final bean definition to use (potentially a proxy)
|
||||
*/
|
||||
private BeanDefinitionHolder applyScopedProxyMode(BeanDefinitionHolder definition, ScopeMetadata metadata) {
|
||||
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
|
||||
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
|
||||
return definition;
|
||||
}
|
||||
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
|
||||
return ScopedProxyCreator.createScopedProxy(definition, this.registry, proxyTargetClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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.annotation;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
|
||||
/**
|
||||
* Standalone application context, accepting annotated classes as input - in particular
|
||||
* {@link org.springframework.context.annotation.Configuration @Configuration}-annotated
|
||||
* classes, but also plain {@link org.springframework.stereotype.Component @Components}
|
||||
* and JSR-330 compliant classes using {@literal javax.inject} annotations. Allows for
|
||||
* registering classes one by one ({@link #register}) as well as for classpath scanning
|
||||
* ({@link #scan}).
|
||||
*
|
||||
* <p>Useful for test harnesses or any other scenario where XML-based configuration
|
||||
* is unnecessary or undesired.
|
||||
*
|
||||
* <p>In case of multiple Configuration classes, {@link Bean} methods defined in later
|
||||
* classes will override those defined in earlier classes. This can be leveraged to
|
||||
* deliberately override certain bean definitions via an extra Configuration class.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see AnnotatedBeanDefinitionReader
|
||||
* @see ClassPathBeanDefinitionScanner
|
||||
*/
|
||||
public class AnnotationConfigApplicationContext extends GenericApplicationContext {
|
||||
|
||||
private final AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(this);
|
||||
|
||||
private final ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this);
|
||||
|
||||
|
||||
/**
|
||||
* Create a new AnnotationConfigApplicationContext that needs to be populated
|
||||
* through {@link #add} calls and then manually {@link #refresh refreshed}.
|
||||
*/
|
||||
public AnnotationConfigApplicationContext() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new AnnotationConfigApplicationContext, deriving bean
|
||||
* definitions from the given annotated classes and automatically
|
||||
* refreshing the context.
|
||||
* @param annotatedClasses one or more annotated classes,
|
||||
* e.g. {@link Configuration @Configuration} classes
|
||||
*/
|
||||
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
|
||||
register(annotatedClasses);
|
||||
refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new AnnotationConfigApplicationContext, scanning for bean
|
||||
* definitions in the given packages and automatically refreshing the
|
||||
* context.
|
||||
* @param basePackages the packages to check for annotated classes
|
||||
*/
|
||||
public AnnotationConfigApplicationContext(String... basePackages) {
|
||||
scan(basePackages);
|
||||
refresh();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the BeanNameGenerator to use for detected bean classes.
|
||||
* <p>Default is a {@link AnnotationBeanNameGenerator}.
|
||||
*/
|
||||
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
|
||||
this.reader.setBeanNameGenerator(beanNameGenerator);
|
||||
this.scanner.setBeanNameGenerator(beanNameGenerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ScopeMetadataResolver to use for detected bean classes.
|
||||
* <p>The default is an {@link AnnotationScopeMetadataResolver}.
|
||||
*/
|
||||
public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
|
||||
this.reader.setScopeMetadataResolver(scopeMetadataResolver);
|
||||
this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register an annotated class to be processed. Allows for programmatically
|
||||
* building a {@link AnnotationConfigApplicationContext}. Note that
|
||||
* {@link AnnotationConfigApplicationContext#refresh()} must be called in
|
||||
* order for the context to fully process the new class.
|
||||
* <p>Calls to {@link #register} are idempotent; adding the same
|
||||
* annotated class more than once has no additional effect.
|
||||
* @param annotatedClasses one or more annotated classes,
|
||||
* e.g. {@link Configuration @Configuration} classes
|
||||
* @see #refresh()
|
||||
*/
|
||||
public void register(Class<?>... annotatedClasses) {
|
||||
this.reader.register(annotatedClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a scan within the specified base packages.
|
||||
* @param basePackages the packages to check for annotated classes
|
||||
*/
|
||||
public void scan(String[] basePackages) {
|
||||
this.scanner.scan(basePackages);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package org.springframework.context.annotation;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
|
||||
import org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
@@ -160,4 +161,29 @@ public class AnnotationConfigUtils {
|
||||
return new BeanDefinitionHolder(definition, beanName);
|
||||
}
|
||||
|
||||
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
|
||||
if (abd.getMetadata().isAnnotated(Primary.class.getName())) {
|
||||
abd.setPrimary(true);
|
||||
}
|
||||
if (abd.getMetadata().isAnnotated(Lazy.class.getName())) {
|
||||
Boolean value = (Boolean) abd.getMetadata().getAnnotationAttributes(Lazy.class.getName()).get("value");
|
||||
abd.setLazyInit(value);
|
||||
}
|
||||
if (abd.getMetadata().isAnnotated(DependsOn.class.getName())) {
|
||||
String[] value = (String[]) abd.getMetadata().getAnnotationAttributes(DependsOn.class.getName()).get("value");
|
||||
abd.setDependsOn(value);
|
||||
}
|
||||
}
|
||||
|
||||
static BeanDefinitionHolder applyScopedProxyMode(
|
||||
ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
|
||||
|
||||
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
|
||||
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
|
||||
return definition;
|
||||
}
|
||||
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
|
||||
return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.springframework.util.PatternMatchUtils;
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
* @see AnnotationConfigApplicationContext#scan
|
||||
* @see org.springframework.stereotype.Component
|
||||
* @see org.springframework.stereotype.Repository
|
||||
* @see org.springframework.stereotype.Service
|
||||
@@ -145,7 +146,7 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
|
||||
* @see #setScopedProxyMode
|
||||
*/
|
||||
public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
|
||||
this.scopeMetadataResolver = scopeMetadataResolver;
|
||||
this.scopeMetadataResolver = (scopeMetadataResolver != null ? scopeMetadataResolver : new AnnotationScopeMetadataResolver());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,22 +207,11 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
|
||||
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
|
||||
}
|
||||
if (candidate instanceof AnnotatedBeanDefinition) {
|
||||
AnnotatedBeanDefinition abd = (AnnotatedBeanDefinition) candidate;
|
||||
if (abd.getMetadata().isAnnotated(Primary.class.getName())) {
|
||||
abd.setPrimary(true);
|
||||
}
|
||||
if (abd.getMetadata().isAnnotated(Lazy.class.getName())) {
|
||||
Boolean value = (Boolean) abd.getMetadata().getAnnotationAttributes(Lazy.class.getName()).get("value");
|
||||
abd.setLazyInit(value);
|
||||
}
|
||||
if (abd.getMetadata().isAnnotated(DependsOn.class.getName())) {
|
||||
String[] value = (String[]) abd.getMetadata().getAnnotationAttributes(DependsOn.class.getName()).get("value");
|
||||
abd.setDependsOn(value);
|
||||
}
|
||||
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
|
||||
}
|
||||
if (checkCandidate(beanName, candidate)) {
|
||||
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
|
||||
definitionHolder = applyScopedProxyMode(definitionHolder, scopeMetadata);
|
||||
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
|
||||
beanDefinitions.add(definitionHolder);
|
||||
registerBeanDefinition(definitionHolder, this.registry);
|
||||
}
|
||||
@@ -300,19 +290,4 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
|
||||
newDefinition.equals(existingDefinition)); // scanned equivalent class twice
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the specified scope to the given bean definition.
|
||||
* @param definition the bean definition to configure
|
||||
* @param metadata the corresponding scope metadata
|
||||
* @return the final bean definition to use (potentially a proxy)
|
||||
*/
|
||||
private BeanDefinitionHolder applyScopedProxyMode(BeanDefinitionHolder definition, ScopeMetadata metadata) {
|
||||
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
|
||||
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
|
||||
return definition;
|
||||
}
|
||||
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
|
||||
return ScopedProxyCreator.createScopedProxy(definition, this.registry, proxyTargetClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ import org.springframework.stereotype.Component;
|
||||
* @see Lazy
|
||||
* @see Bean
|
||||
* @see ConfigurationClassPostProcessor;
|
||||
* @see ConfigurationClassApplicationContext;
|
||||
* @see AnnotationConfigApplicationContext ;
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@@ -70,7 +70,7 @@ public @interface Configuration {
|
||||
* a bean name will be automatically generated.
|
||||
*
|
||||
* <p>The custom name applies only if the Configuration class is picked up via
|
||||
* component scanning or supplied directly to a {@link ConfigurationClassApplicationContext}.
|
||||
* component scanning or supplied directly to a {@link AnnotationConfigApplicationContext}.
|
||||
* If the Configuration class is registered as a traditional XML bean definition,
|
||||
* the name/id of the bean element will take precedence.
|
||||
*
|
||||
|
||||
@@ -1,192 +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.annotation;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.DefaultBeanNameGenerator;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.support.AbstractRefreshableApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Standalone application context, accepting {@link Configuration @Configuration}
|
||||
* -annotated class literals as input. Useful for test harnesses or any other scenario
|
||||
* where XML-based configuration is unnecessary or undesired.
|
||||
*
|
||||
* <p>In case of multiple Configuration classes, {@link Bean}
|
||||
* methods defined in later classes will override those defined in earlier
|
||||
* classes. This can be leveraged to deliberately override certain bean
|
||||
* definitions via an extra Configuration class.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.0
|
||||
* @see Configuration
|
||||
*/
|
||||
public class ConfigurationClassApplicationContext extends AbstractRefreshableApplicationContext {
|
||||
|
||||
private final ConfigurationClassApplicationContext.Delegate delegate =
|
||||
new ConfigurationClassApplicationContext.Delegate();
|
||||
|
||||
/**
|
||||
* Create a new {@link ConfigurationClassApplicationContext}, loading bean
|
||||
* definitions from the given {@literal configClasses} and automatically
|
||||
* refreshing the context. <p>Note: if zero classes are specified, the
|
||||
* context will <b>not</b> be refreshed automatically, assuming that
|
||||
* the user will subsequently call {@link #addConfigurationClass(Class)}
|
||||
* and then manually refresh.
|
||||
*
|
||||
* @param configClasses zero or more {@link Configuration} classes
|
||||
* @see #addConfigurationClass(Class)
|
||||
* @see #refresh()
|
||||
*/
|
||||
public ConfigurationClassApplicationContext(Class<?>... configClasses) {
|
||||
if (configClasses.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Class<?> configClass : configClasses) {
|
||||
this.addConfigurationClass(configClass);
|
||||
}
|
||||
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a {@link Configuration} class to be processed. Allows for programmatically
|
||||
* building a {@link ConfigurationClassApplicationContext}. Note that
|
||||
* {@link ConfigurationClassApplicationContext#refresh()} must be called in
|
||||
* order for the context to process the new class. Calls to
|
||||
* {@link #addConfigurationClass(Class)} are idempotent; adding the same
|
||||
* Configuration class more than once has no additional effect.
|
||||
* @param configClass new Configuration class to be processed.
|
||||
* @see #ConfigurationClassApplicationContext(Class...)
|
||||
* @see #refresh()
|
||||
*/
|
||||
public void addConfigurationClass(Class<?> configClass) {
|
||||
this.delegate.addConfigurationClass(configClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link BeanDefinition} for each {@link Configuration @Configuration}
|
||||
* class specified. Enables the default set of annotation configuration post
|
||||
* processors, such that {@literal @Autowired}, {@literal @Required}, and associated
|
||||
* annotations can be used within Configuration classes.
|
||||
*
|
||||
* <p>Configuration class bean definitions are registered with generated bean definition
|
||||
* names unless the {@literal value} attribute is provided to the Configuration annotation.
|
||||
*
|
||||
* @see AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry)
|
||||
* @see ConfigurationClassPostProcessor
|
||||
* @see DefaultBeanNameGenerator
|
||||
* @see Configuration#value()
|
||||
*/
|
||||
@Override
|
||||
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
|
||||
this.delegate.loadBeanDefinitions(beanFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean instance that matches the given object type.
|
||||
*
|
||||
* @param <T>
|
||||
* @param requiredType type the bean must match; can be an interface or superclass.
|
||||
* {@literal null} is disallowed.
|
||||
* @return bean matching required type
|
||||
* @throws NoSuchBeanDefinitionException if there is not exactly one matching bean
|
||||
* found
|
||||
* @see org.springframework.beans.factory.ListableBeanFactory#getBeansOfType(Class)
|
||||
* @see org.springframework.beans.factory.BeanFactory#getBean(String, Class)
|
||||
*/
|
||||
public <T> T getBean(Class<T> requiredType) {
|
||||
return this.delegate.getBean(requiredType, this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encapsulates behavior common to {@link ConfigurationClassApplicationContext}
|
||||
* and its {@link org.springframework.web.context.support.ConfigurationClassWebApplicationContext}
|
||||
* variant. Both classes already participate in mutually exclusive superclass
|
||||
* hierarchies, and this class allows for avoiding what would otherwise be a multiple
|
||||
* inheritance problem through composition.
|
||||
*
|
||||
* <p><strong>This class is public by necessity but should be considered private and
|
||||
* subject to change without notice.</strong>
|
||||
*/
|
||||
public static class Delegate {
|
||||
|
||||
private final Set<Class<?>> configClasses = new LinkedHashSet<Class<?>>();
|
||||
|
||||
/**
|
||||
* @see ConfigurationClassApplicationContext#addConfigurationClass(Class)
|
||||
*/
|
||||
public void addConfigurationClass(Class<?> configClass) {
|
||||
Assert.notNull(
|
||||
AnnotationUtils.findAnnotation(configClass, Configuration.class),
|
||||
"Class [" + configClass.getName() + "] is not annotated with @Configuration");
|
||||
this.configClasses.add(configClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ConfigurationClassApplicationContext#loadBeanDefinitions(DefaultListableBeanFactory)
|
||||
*/
|
||||
public void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
|
||||
// @Autowired and friends must be enabled by default when processing @Configuration classes
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
|
||||
|
||||
for (Class<?> configClass : this.configClasses) {
|
||||
RootBeanDefinition def = new RootBeanDefinition(configClass);
|
||||
String name = AnnotationUtils.findAnnotation(configClass, Configuration.class).value();
|
||||
if (!StringUtils.hasLength(name)) {
|
||||
name = new DefaultBeanNameGenerator().generateBeanName(def, beanFactory);
|
||||
}
|
||||
beanFactory.registerBeanDefinition(name, def);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ConfigurationClassApplicationContext#getBean(Class)
|
||||
*/
|
||||
public <T> T getBean(Class<T> requiredType, ListableBeanFactory context) {
|
||||
Assert.notNull(requiredType, "requiredType may not be null");
|
||||
Assert.notNull(context, "context may not be null");
|
||||
Map<String, T> beansOfType = context.getBeansOfType(requiredType);
|
||||
switch (beansOfType.size()) {
|
||||
case 0:
|
||||
throw new NoSuchBeanDefinitionException(requiredType);
|
||||
case 1:
|
||||
return beansOfType.values().iterator().next();
|
||||
default:
|
||||
throw new NoSuchBeanDefinitionException(requiredType,
|
||||
beansOfType.size() + " matching bean definitions found " +
|
||||
"(" + StringUtils.collectionToCommaDelimitedString(beansOfType.keySet()) + "). " +
|
||||
"Consider qualifying with getBean(Class<T> beanType, String beanName) or " +
|
||||
"declaring one bean definition as @Primary");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -49,7 +49,7 @@ import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
* specific bean definition format, are {@link ClassPathXmlApplicationContext}
|
||||
* and {@link FileSystemXmlApplicationContext}, which both derive from the
|
||||
* common {@link AbstractXmlApplicationContext} base class;
|
||||
* {@link org.springframework.context.annotation.ConfigurationClassApplicationContext}
|
||||
* {@link org.springframework.context.annotation.AnnotationConfigApplicationContext}
|
||||
* supports {@literal @Configuration}-annotated classes as a source of bean definitions.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
@@ -60,7 +60,7 @@ import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
* @see AbstractXmlApplicationContext
|
||||
* @see ClassPathXmlApplicationContext
|
||||
* @see FileSystemXmlApplicationContext
|
||||
* @see org.springframework.context.annotation.ConfigurationClassApplicationContext
|
||||
* @see org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
*/
|
||||
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
|
||||
|
||||
@@ -223,12 +223,12 @@ public abstract class AbstractRefreshableApplicationContext extends AbstractAppl
|
||||
* Load bean definitions into the given bean factory, typically through
|
||||
* delegating to one or more bean definition readers.
|
||||
* @param beanFactory the bean factory to load bean definitions into
|
||||
* @throws IOException if loading of bean definition files failed
|
||||
* @throws BeansException if parsing of the bean definitions failed
|
||||
* @throws IOException if loading of bean definition files failed
|
||||
* @see org.springframework.beans.factory.support.PropertiesBeanDefinitionReader
|
||||
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
|
||||
*/
|
||||
protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
|
||||
throws IOException, BeansException;
|
||||
throws BeansException, IOException;
|
||||
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public abstract class AbstractXmlApplicationContext extends AbstractRefreshableC
|
||||
* @see #loadBeanDefinitions
|
||||
*/
|
||||
@Override
|
||||
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
|
||||
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
|
||||
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
|
||||
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user