full compliance with the JSR-330 TCK
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* 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.lang.annotation.Annotation;
|
||||
|
||||
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Convenient adapter for programmatic registration of annotated bean classes.
|
||||
*
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class AnnotatedBeanDefinitionReader {
|
||||
|
||||
private final BeanDefinitionRegistry registry;
|
||||
|
||||
private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
|
||||
|
||||
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
|
||||
|
||||
private boolean includeAnnotationConfig = true;
|
||||
|
||||
|
||||
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the BeanDefinitionRegistry that this scanner operates on.
|
||||
*/
|
||||
public final BeanDefinitionRegistry getRegistry() {
|
||||
return this.registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the BeanNameGenerator to use for detected bean classes.
|
||||
* <p>Default is a {@link AnnotationBeanNameGenerator}.
|
||||
*/
|
||||
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
|
||||
this.beanNameGenerator = (beanNameGenerator != null ? beanNameGenerator : new AnnotationBeanNameGenerator());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
public void registerBeans(Class<?>... annotatedClasses) {
|
||||
for (Class<?> annotatedClass : annotatedClasses) {
|
||||
registerBean(annotatedClass);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerBean(Class<?> annotatedClass) {
|
||||
registerBean(annotatedClass, null, (Class<? extends Annotation>[]) null);
|
||||
}
|
||||
|
||||
public void registerBean(Class<?> annotatedClass, Class<? extends Annotation>... qualifiers) {
|
||||
registerBean(annotatedClass, null, qualifiers);
|
||||
}
|
||||
|
||||
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
|
||||
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
|
||||
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);
|
||||
}
|
||||
if (qualifiers != null) {
|
||||
for (Class<? extends Annotation> qualifier : qualifiers) {
|
||||
if (Primary.class.equals(qualifier)) {
|
||||
abd.setPrimary(true);
|
||||
}
|
||||
else if (Lazy.class.equals(qualifier)) {
|
||||
abd.setLazyInit(true);
|
||||
}
|
||||
else {
|
||||
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
|
||||
}
|
||||
}
|
||||
}
|
||||
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
|
||||
definitionHolder = applyScopedProxyMode(definitionHolder, scopeMetadata);
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -315,5 +315,4 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
|
||||
return ScopedProxyCreator.createScopedProxy(definition, this.registry, proxyTargetClass);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -62,7 +63,6 @@ import org.springframework.core.Ordered;
|
||||
import org.springframework.jndi.support.SimpleJndiBeanFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -283,13 +283,6 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||
}
|
||||
|
||||
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
|
||||
InjectionMetadata metadata = findResourceMetadata(bean.getClass());
|
||||
try {
|
||||
metadata.injectFields(bean, beanName);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new BeanCreationException(beanName, "Injection of resource fields failed", ex);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -298,10 +291,10 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||
|
||||
InjectionMetadata metadata = findResourceMetadata(bean.getClass());
|
||||
try {
|
||||
metadata.injectMethods(bean, beanName, pvs);
|
||||
metadata.inject(bean, beanName, pvs);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new BeanCreationException(beanName, "Injection of resource methods failed", ex);
|
||||
throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
|
||||
}
|
||||
return pvs;
|
||||
}
|
||||
@@ -314,33 +307,34 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||
synchronized (this.injectionMetadataCache) {
|
||||
metadata = this.injectionMetadataCache.get(clazz);
|
||||
if (metadata == null) {
|
||||
final InjectionMetadata newMetadata = new InjectionMetadata(clazz);
|
||||
ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() {
|
||||
public void doWith(Field field) {
|
||||
LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
|
||||
Class<?> targetClass = clazz;
|
||||
|
||||
do {
|
||||
LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<InjectionMetadata.InjectedElement>();
|
||||
for (Field field : targetClass.getDeclaredFields()) {
|
||||
if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
|
||||
}
|
||||
newMetadata.addInjectedField(new WebServiceRefElement(field, null));
|
||||
currElements.add(new WebServiceRefElement(field, null));
|
||||
}
|
||||
else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
throw new IllegalStateException("@EJB annotation is not supported on static fields");
|
||||
}
|
||||
newMetadata.addInjectedField(new EjbRefElement(field, null));
|
||||
currElements.add(new EjbRefElement(field, null));
|
||||
}
|
||||
else if (field.isAnnotationPresent(Resource.class)) {
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
throw new IllegalStateException("@Resource annotation is not supported on static fields");
|
||||
}
|
||||
if (!ignoredResourceTypes.contains(field.getType().getName())) {
|
||||
newMetadata.addInjectedField(new ResourceElement(field, null));
|
||||
currElements.add(new ResourceElement(field, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() {
|
||||
public void doWith(Method method) {
|
||||
for (Method method : targetClass.getDeclaredMethods()) {
|
||||
if (webServiceRefClass != null && method.isAnnotationPresent(webServiceRefClass) &&
|
||||
method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
|
||||
if (Modifier.isStatic(method.getModifiers())) {
|
||||
@@ -350,7 +344,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||
throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
|
||||
}
|
||||
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
|
||||
newMetadata.addInjectedMethod(new WebServiceRefElement(method, pd));
|
||||
currElements.add(new WebServiceRefElement(method, pd));
|
||||
}
|
||||
else if (ejbRefClass != null && method.isAnnotationPresent(ejbRefClass) &&
|
||||
method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
|
||||
@@ -361,7 +355,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||
throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
|
||||
}
|
||||
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
|
||||
newMetadata.addInjectedMethod(new EjbRefElement(method, pd));
|
||||
currElements.add(new EjbRefElement(method, pd));
|
||||
}
|
||||
else if (method.isAnnotationPresent(Resource.class) &&
|
||||
method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
|
||||
@@ -374,12 +368,16 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||
}
|
||||
if (!ignoredResourceTypes.contains(paramTypes[0].getName())) {
|
||||
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
|
||||
newMetadata.addInjectedMethod(new ResourceElement(method, pd));
|
||||
currElements.add(new ResourceElement(method, pd));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
metadata = newMetadata;
|
||||
elements.addAll(0, currElements);
|
||||
targetClass = targetClass.getSuperclass();
|
||||
}
|
||||
while (targetClass != null && targetClass != Object.class);
|
||||
|
||||
metadata = new InjectionMetadata(clazz, elements);
|
||||
this.injectionMetadataCache.put(clazz, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,19 +16,16 @@
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
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.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.DefaultBeanNameGenerator;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.support.AbstractRefreshableApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -108,8 +105,7 @@ public class ConfigurationClassApplicationContext extends AbstractRefreshableApp
|
||||
* @see Configuration#value()
|
||||
*/
|
||||
@Override
|
||||
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
|
||||
throws IOException, BeansException {
|
||||
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
|
||||
this.delegate.loadBeanDefinitions(beanFactory);
|
||||
}
|
||||
|
||||
@@ -162,34 +158,27 @@ public class ConfigurationClassApplicationContext extends AbstractRefreshableApp
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
|
||||
|
||||
for (Class<?> configClass : this.configClasses) {
|
||||
AbstractBeanDefinition def = BeanDefinitionBuilder.rootBeanDefinition(configClass).getBeanDefinition();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ConfigurationClassApplicationContext#getBean(Class)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getBean(Class<T> requiredType, AbstractApplicationContext context) {
|
||||
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, ?> beansOfType = context.getBeansOfType(requiredType);
|
||||
|
||||
Map<String, T> beansOfType = context.getBeansOfType(requiredType);
|
||||
switch (beansOfType.size()) {
|
||||
case 0:
|
||||
throw new NoSuchBeanDefinitionException(requiredType);
|
||||
case 1:
|
||||
return (T) beansOfType.values().iterator().next();
|
||||
return beansOfType.values().iterator().next();
|
||||
default:
|
||||
throw new NoSuchBeanDefinitionException(requiredType,
|
||||
beansOfType.size() + " matching bean definitions found " +
|
||||
@@ -199,4 +188,5 @@ public class ConfigurationClassApplicationContext extends AbstractRefreshableApp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user