next cut of JavaConfig metadata reading revision: using cached MetadataReaders
This commit is contained in:
@@ -192,8 +192,8 @@ public class QualifierAnnotationAutowireCandidateResolver implements AutowireCan
|
||||
}
|
||||
if (qualifier == null) {
|
||||
Annotation targetAnnotation = null;
|
||||
if (bd.getFactoryMethodForIntrospection() != null) {
|
||||
targetAnnotation = bd.getFactoryMethodForIntrospection().getAnnotation(type);
|
||||
if (bd.getResolvedFactoryMethod() != null) {
|
||||
targetAnnotation = bd.getResolvedFactoryMethod().getAnnotation(type);
|
||||
}
|
||||
if (targetAnnotation == null && bd.hasBeanClass()) {
|
||||
// look for matching annotation on the target class
|
||||
|
||||
@@ -1025,7 +1025,12 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
if (mbd == null) {
|
||||
if (bd.getParentName() == null) {
|
||||
// Use copy of given root bean definition.
|
||||
mbd = new RootBeanDefinition(bd);
|
||||
if (bd instanceof RootBeanDefinition) {
|
||||
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
|
||||
}
|
||||
else {
|
||||
mbd = new RootBeanDefinition(bd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Child bean definition: needs to be merged with parent.
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
@@ -43,10 +44,10 @@ import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.beans.factory.config.TypedStringValue;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.MethodInvoker;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Helper class for resolving constructors and factory methods.
|
||||
@@ -247,6 +248,36 @@ class ConstructorResolver {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the factory method in the specified bean definition, if possible.
|
||||
* {@link RootBeanDefinition#getResolvedFactoryMethod()} can be checked for the result.
|
||||
* @param mbd the bean definition to check
|
||||
*/
|
||||
public void resolveFactoryMethodIfPossible(RootBeanDefinition mbd) {
|
||||
Class factoryClass;
|
||||
if (mbd.getFactoryBeanName() != null) {
|
||||
factoryClass = this.beanFactory.getType(mbd.getFactoryBeanName());
|
||||
}
|
||||
else {
|
||||
factoryClass = mbd.getBeanClass();
|
||||
}
|
||||
factoryClass = ClassUtils.getUserClass(factoryClass);
|
||||
Method[] candidates = ReflectionUtils.getAllDeclaredMethods(factoryClass);
|
||||
Method uniqueCandidate = null;
|
||||
for (Method candidate : candidates) {
|
||||
if (mbd.isFactoryMethod(candidate)) {
|
||||
if (uniqueCandidate == null) {
|
||||
uniqueCandidate = candidate;
|
||||
}
|
||||
else if (!Arrays.equals(uniqueCandidate.getParameterTypes(), candidate.getParameterTypes())) {
|
||||
uniqueCandidate = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate the bean using a named factory method. The method may be static, if the
|
||||
* bean definition parameter specifies a class, rather than a "factory-bean", or
|
||||
@@ -306,13 +337,13 @@ class ConstructorResolver {
|
||||
if (factoryMethodToUse != null) {
|
||||
// Found a cached factory method...
|
||||
argsToUse = mbd.resolvedConstructorArguments;
|
||||
if (argsToUse == null) {
|
||||
if (argsToUse == null && mbd.preparedConstructorArguments != null) {
|
||||
argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (factoryMethodToUse == null) {
|
||||
if (factoryMethodToUse == null || argsToUse == null) {
|
||||
// Need to determine the factory method...
|
||||
// Try all methods with this name to see if they match the given arguments.
|
||||
factoryClass = ClassUtils.getUserClass(factoryClass);
|
||||
@@ -320,7 +351,8 @@ class ConstructorResolver {
|
||||
List<Method> candidateSet = new ArrayList<Method>();
|
||||
for (Method candidate : rawCandidates) {
|
||||
if (Modifier.isStatic(candidate.getModifiers()) == isStatic &&
|
||||
candidate.getName().equals(mbd.getFactoryMethodName())) {
|
||||
candidate.getName().equals(mbd.getFactoryMethodName()) &&
|
||||
mbd.isFactoryMethod(candidate)) {
|
||||
candidateSet.add(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,7 @@
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -49,9 +47,7 @@ import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -432,31 +428,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
*/
|
||||
protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd, DependencyDescriptor descriptor) {
|
||||
resolveBeanClass(mbd, beanName);
|
||||
// TODO: the following is duplicating the factory method resolution algorithm in
|
||||
// ConstructorResolver quite a bit...
|
||||
if (mbd.getFactoryMethodName() != null && mbd.factoryMethodForIntrospection == null) {
|
||||
Class factoryClass;
|
||||
if (mbd.getFactoryBeanName() != null) {
|
||||
factoryClass = getType(mbd.getFactoryBeanName());
|
||||
}
|
||||
else {
|
||||
factoryClass = mbd.getBeanClass();
|
||||
}
|
||||
factoryClass = ClassUtils.getUserClass(factoryClass);
|
||||
Method[] candidates = ReflectionUtils.getAllDeclaredMethods(factoryClass);
|
||||
Method uniqueCandidate = null;
|
||||
for (Method candidate : candidates) {
|
||||
if (candidate.getName().equals(mbd.getFactoryMethodName())) {
|
||||
if (uniqueCandidate == null) {
|
||||
uniqueCandidate = candidate;
|
||||
}
|
||||
else if (!Arrays.equals(uniqueCandidate.getParameterTypes(), candidate.getParameterTypes())) {
|
||||
uniqueCandidate = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
mbd.factoryMethodForIntrospection = uniqueCandidate;
|
||||
if (mbd.isFactoryMethodUnique && mbd.resolvedConstructorOrFactoryMethod == null) {
|
||||
new ConstructorResolver(this, null, null, null).resolveFactoryMethodIfPossible(mbd);
|
||||
}
|
||||
return getAutowireCandidateResolver().isAutowireCandidate(
|
||||
new BeanDefinitionHolder(mbd, beanName, getAliases(beanName)), descriptor);
|
||||
|
||||
@@ -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.
|
||||
@@ -25,6 +25,7 @@ import java.util.Set;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A root bean definition represents the merged bean definition that backs
|
||||
@@ -52,7 +53,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
|
||||
private final Set<String> externallyManagedDestroyMethods = Collections.synchronizedSet(new HashSet<String>());
|
||||
|
||||
volatile Method factoryMethodForIntrospection;
|
||||
boolean isFactoryMethodUnique;
|
||||
|
||||
/** Package-visible field for caching the resolved constructor or factory method */
|
||||
volatile Object resolvedConstructorOrFactoryMethod;
|
||||
@@ -198,7 +199,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
* @param original the original bean definition to copy from
|
||||
*/
|
||||
public RootBeanDefinition(RootBeanDefinition original) {
|
||||
super((BeanDefinition) original);
|
||||
this((BeanDefinition) original);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,6 +209,9 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
*/
|
||||
RootBeanDefinition(BeanDefinition original) {
|
||||
super(original);
|
||||
if (original instanceof RootBeanDefinition) {
|
||||
this.isFactoryMethodUnique = ((RootBeanDefinition) original).isFactoryMethodUnique;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -221,8 +225,26 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
public Method getFactoryMethodForIntrospection() {
|
||||
return this.factoryMethodForIntrospection;
|
||||
/**
|
||||
* Specify a factory method name that refers to a non-overloaded method.
|
||||
*/
|
||||
public void setUniqueFactoryMethodName(String name) {
|
||||
Assert.hasText(name, "Factory method name must not be empty");
|
||||
setFactoryMethodName(name);
|
||||
this.isFactoryMethodUnique = true;
|
||||
}
|
||||
|
||||
public boolean isFactoryMethod(Method candidate) {
|
||||
return (candidate != null && candidate.getName().equals(getFactoryMethodName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the resolved factory method as a Java Method object, if available.
|
||||
* @return the factory method, or <code>null</code> if not found or not resolved yet
|
||||
*/
|
||||
public Method getResolvedFactoryMethod() {
|
||||
Object candidate = this.resolvedConstructorOrFactoryMethod;
|
||||
return (candidate instanceof Method ? (Method) candidate : null);
|
||||
}
|
||||
|
||||
|
||||
@@ -252,7 +274,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractBeanDefinition cloneBeanDefinition() {
|
||||
public RootBeanDefinition cloneBeanDefinition() {
|
||||
return new RootBeanDefinition(this);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user