full compliance with the JSR-330 TCK

This commit is contained in:
Juergen Hoeller
2009-10-20 18:18:25 +00:00
parent a429e230b6
commit 94533976d0
12 changed files with 434 additions and 164 deletions

View File

@@ -27,6 +27,7 @@ import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -270,28 +271,16 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
InjectionMetadata metadata = findAutowiringMetadata(bean.getClass());
try {
metadata.injectFields(bean, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Autowiring of fields failed", ex);
}
return true;
}
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
InjectionMetadata metadata = findAutowiringMetadata(bean.getClass());
try {
metadata.injectMethods(bean, beanName, pvs);
metadata.inject(bean, beanName, pvs);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Autowiring of methods failed", ex);
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
@@ -300,15 +289,16 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
* 'Native' processing method for direct calls with an arbitrary target instance,
* resolving all of its fields and methods which are annotated with <code>@Autowired</code>.
* @param bean the target instance to process
* @throws BeansException if autowiring failed
*/
public void processInjection(Object bean) throws BeansException {
InjectionMetadata metadata = findAutowiringMetadata(bean.getClass());
Class<?> clazz = bean.getClass();
InjectionMetadata metadata = findAutowiringMetadata(clazz);
try {
metadata.injectFields(bean, null);
metadata.injectMethods(bean, null, null);
metadata.inject(bean, null, null);
}
catch (Throwable ex) {
throw new BeanCreationException("Autowiring of fields/methods failed", ex);
throw new BeanCreationException("Injection of autowired dependencies failed for class [" + clazz + "]", ex);
}
}
@@ -320,36 +310,49 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
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()) {
Annotation annotation = findAutowiredAnnotation(field);
if (annotation != null) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("Autowired annotation is not supported on static fields");
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static fields: " + field);
}
continue;
}
boolean required = determineRequiredStatus(annotation);
newMetadata.addInjectedField(new AutowiredFieldElement(field, required));
currElements.add(new AutowiredFieldElement(field, required));
}
}
});
ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() {
public void doWith(Method method) {
for (Method method : targetClass.getDeclaredMethods()) {
Annotation annotation = findAutowiredAnnotation(method);
if (annotation != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("Autowired annotation is not supported on static methods");
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static methods: " + method);
}
continue;
}
if (method.getParameterTypes().length == 0) {
throw new IllegalStateException("Autowired annotation requires at least one argument: " + method);
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation should be used on methods with actual parameters: " + method);
}
}
boolean required = determineRequiredStatus(annotation);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
newMetadata.addInjectedMethod(new AutowiredMethodElement(method, required, pd));
currElements.add(new AutowiredMethodElement(method, required, 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);
}
}

View File

@@ -49,42 +49,21 @@ public class InjectionMetadata {
private final Log logger = LogFactory.getLog(InjectionMetadata.class);
private String targetClassName;
private final Set<InjectedElement> injectedFields = new LinkedHashSet<InjectedElement>();
private final Set<InjectedElement> injectedMethods = new LinkedHashSet<InjectedElement>();
private final Set<InjectedElement> injectedElements;
public InjectionMetadata() {
}
public InjectionMetadata(Class targetClass) {
this.targetClassName = targetClass.getName();
}
public void addInjectedField(InjectedElement element) {
if (logger.isDebugEnabled()) {
logger.debug("Found injected field on class [" + this.targetClassName + "]: " + element);
public InjectionMetadata(Class targetClass, Collection<InjectedElement> elements) {
this.injectedElements = new LinkedHashSet<InjectedElement>();
for (InjectedElement element : elements) {
if (logger.isDebugEnabled()) {
logger.debug("Found injected element on class [" + targetClass.getName() + "]: " + element);
}
this.injectedElements.add(element);
}
this.injectedFields.add(element);
}
public void addInjectedMethod(InjectedElement element) {
if (logger.isDebugEnabled()) {
logger.debug("Found injected method on class [" + this.targetClassName + "]: " + element);
}
this.injectedMethods.add(element);
}
public void checkConfigMembers(RootBeanDefinition beanDefinition) {
doRegisterConfigMembers(beanDefinition, this.injectedFields);
doRegisterConfigMembers(beanDefinition, this.injectedMethods);
}
private void doRegisterConfigMembers(RootBeanDefinition beanDefinition, Collection<InjectedElement> members) {
for (Iterator<InjectedElement> it = members.iterator(); it.hasNext();) {
for (Iterator<InjectedElement> it = this.injectedElements.iterator(); it.hasNext();) {
Member member = it.next().getMember();
if (!beanDefinition.isExternallyManagedConfigMember(member)) {
beanDefinition.registerExternallyManagedConfigMember(member);
@@ -95,22 +74,10 @@ public class InjectionMetadata {
}
}
public void injectFields(Object target, String beanName) throws Throwable {
if (!this.injectedFields.isEmpty()) {
public void inject(Object target, String beanName, PropertyValues pvs) throws Throwable {
if (!this.injectedElements.isEmpty()) {
boolean debug = logger.isDebugEnabled();
for (InjectedElement element : this.injectedFields) {
if (debug) {
logger.debug("Processing injected field of bean '" + beanName + "': " + element);
}
element.inject(target, beanName, null);
}
}
}
public void injectMethods(Object target, String beanName, PropertyValues pvs) throws Throwable {
if (!this.injectedMethods.isEmpty()) {
boolean debug = logger.isDebugEnabled();
for (InjectedElement element : this.injectedMethods) {
for (InjectedElement element : this.injectedElements) {
if (debug) {
logger.debug("Processing injected method of bean '" + beanName + "': " + element);
}

View File

@@ -780,12 +780,18 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class beanType, String beanName)
throws BeansException {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
try {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
catch (Exception ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing failed of bean type [" + beanType + "] failed", ex);
}
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* 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.
@@ -16,12 +16,10 @@
package org.springframework.beans.factory.support;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -152,8 +150,8 @@ public class BeanDefinitionReaderUtils {
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (int i = 0; i < aliases.length; i++) {
registry.registerAlias(beanName, aliases[i]);
for (String aliase : aliases) {
registry.registerAlias(beanName, aliase);
}
}
}