revised support for annotated factory methods (merged @FactoryMethod functionality into JavaConfig facility)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.
|
||||
@@ -34,14 +34,6 @@ import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
*/
|
||||
public enum Autowire {
|
||||
|
||||
/**
|
||||
* Constant that indicates that autowiring information was not specified.
|
||||
* In some cases it may be necessary to specify autowiring status,
|
||||
* but merely confirm that this should be inherited from an enclosing
|
||||
* container definition scope.
|
||||
*/
|
||||
INHERITED(-1),
|
||||
|
||||
/**
|
||||
* Constant that indicates no autowiring at all.
|
||||
*/
|
||||
|
||||
@@ -54,7 +54,6 @@ import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.PriorityOrdered;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -102,8 +101,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
protected final Log logger = LogFactory.getLog(AutowiredAnnotationBeanPostProcessor.class);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class<? extends Annotation>[] autowiredAnnotationTypes =
|
||||
new Class[] {Autowired.class, Qualifier.class, Value.class};
|
||||
private Class<? extends Annotation>[] autowiredAnnotationTypes = new Class[] {Autowired.class, Value.class};
|
||||
|
||||
private String requiredParameterName = "required";
|
||||
|
||||
@@ -317,29 +315,19 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
});
|
||||
ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() {
|
||||
public void doWith(Method method) {
|
||||
if (!isFactoryMethod(method)) {
|
||||
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 (method.getParameterTypes().length == 0) {
|
||||
throw new IllegalStateException("Autowired annotation requires at least one argument: " + method);
|
||||
}
|
||||
boolean required = determineRequiredStatus(annotation);
|
||||
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
|
||||
newMetadata.addInjectedMethod(new AutowiredMethodElement(method, required, pd));
|
||||
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 (method.getParameterTypes().length == 0) {
|
||||
throw new IllegalStateException("Autowired annotation requires at least one argument: " + method);
|
||||
}
|
||||
boolean required = determineRequiredStatus(annotation);
|
||||
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
|
||||
newMetadata.addInjectedMethod(new AutowiredMethodElement(method, required, pd));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFactoryMethod(Method method) {
|
||||
if (AnnotationUtils.findAnnotation(method, FactoryMethod.class)!= null) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
metadata = newMetadata;
|
||||
this.injectionMetadataCache.put(clazz, metadata);
|
||||
@@ -429,7 +417,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
|
||||
Field field = (Field) this.member;
|
||||
try {
|
||||
Object value = null;
|
||||
Object value;
|
||||
if (this.cached) {
|
||||
if (this.cachedFieldValue instanceof DependencyDescriptor) {
|
||||
DependencyDescriptor descriptor = (DependencyDescriptor) this.cachedFieldValue;
|
||||
|
||||
@@ -1,36 +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.beans.factory.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Marks a method as being a factory-method of the class. Use during component scanning
|
||||
* to create a bean definition that has factory-bean and factory-method metadata
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @since 3.0
|
||||
* @see RequiredAnnotationBeanPostProcessor
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD})
|
||||
public @interface FactoryMethod {
|
||||
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.beans.factory.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -25,9 +26,9 @@ import org.springframework.beans.SimpleTypeConverter;
|
||||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
|
||||
import org.springframework.beans.factory.support.AutowireCandidateResolver;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -134,8 +135,14 @@ public class QualifierAnnotationAutowireCandidateResolver implements AutowireCan
|
||||
return true;
|
||||
}
|
||||
boolean match = checkQualifiers(bdHolder, descriptor.getAnnotations());
|
||||
if (match && descriptor.getMethodParameter() != null) {
|
||||
match = checkQualifiers(bdHolder, descriptor.getMethodParameter().getAnnotations());
|
||||
if (match) {
|
||||
MethodParameter methodParam = descriptor.getMethodParameter();
|
||||
if (methodParam != null) {
|
||||
Method method = methodParam.getMethod();
|
||||
if (method == null || void.class.equals(method.getReturnType())) {
|
||||
match = checkQualifiers(bdHolder, methodParam.getAnnotations());
|
||||
}
|
||||
}
|
||||
}
|
||||
return match;
|
||||
}
|
||||
@@ -178,15 +185,21 @@ public class QualifierAnnotationAutowireCandidateResolver implements AutowireCan
|
||||
BeanDefinitionHolder bdHolder, Annotation annotation, TypeConverter typeConverter) {
|
||||
|
||||
Class<? extends Annotation> type = annotation.annotationType();
|
||||
AbstractBeanDefinition bd = (AbstractBeanDefinition) bdHolder.getBeanDefinition();
|
||||
RootBeanDefinition bd = (RootBeanDefinition) bdHolder.getBeanDefinition();
|
||||
AutowireCandidateQualifier qualifier = bd.getQualifier(type.getName());
|
||||
if (qualifier == null) {
|
||||
qualifier = bd.getQualifier(ClassUtils.getShortName(type));
|
||||
}
|
||||
if (qualifier == null && bd.hasBeanClass()) {
|
||||
// look for matching annotation on the target class
|
||||
Class<?> beanClass = bd.getBeanClass();
|
||||
Annotation targetAnnotation = beanClass.getAnnotation(type);
|
||||
if (qualifier == null) {
|
||||
Annotation targetAnnotation = null;
|
||||
if (bd.getFactoryMethodForIntrospection() != null) {
|
||||
targetAnnotation = bd.getFactoryMethodForIntrospection().getAnnotation(type);
|
||||
}
|
||||
if (targetAnnotation == null && bd.hasBeanClass()) {
|
||||
// look for matching annotation on the target class
|
||||
Class<?> beanClass = bd.getBeanClass();
|
||||
targetAnnotation = beanClass.getAnnotation(type);
|
||||
}
|
||||
if (targetAnnotation != null && targetAnnotation.equals(annotation)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.beans.factory.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
|
||||
/**
|
||||
* Marker annotation identical in functionality with <aop:scoped-proxy/> tag. Provides a smart
|
||||
* proxy backed by a scoped bean, which can be injected into object instances (usually singletons)
|
||||
* allowing the same reference to be held while delegating method invocations to the backing, scoped
|
||||
* beans.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface ScopedProxy {
|
||||
|
||||
/**
|
||||
* Use CGLib-based class proxies (true) or JDK interface-based (false).
|
||||
*
|
||||
* Default is CGLib (true).
|
||||
* @return
|
||||
*/
|
||||
boolean proxyTargetClass() default true;
|
||||
}
|
||||
@@ -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.
|
||||
@@ -98,7 +98,10 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
* through introspection of the bean class.
|
||||
* @see #createBean
|
||||
* @see #autowire
|
||||
* @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,
|
||||
* prefer annotation-based autowiring for clearer demarcation of autowiring needs.
|
||||
*/
|
||||
@Deprecated
|
||||
int AUTOWIRE_AUTODETECT = 4;
|
||||
|
||||
|
||||
@@ -181,7 +184,6 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
* @see #AUTOWIRE_BY_NAME
|
||||
* @see #AUTOWIRE_BY_TYPE
|
||||
* @see #AUTOWIRE_CONSTRUCTOR
|
||||
* @see #AUTOWIRE_AUTODETECT
|
||||
*/
|
||||
Object createBean(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -143,6 +143,30 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
|
||||
*/
|
||||
void setScope(String scope);
|
||||
|
||||
/**
|
||||
* Return whether this bean should be lazily initialized, i.e. not
|
||||
* eagerly instantiated on startup. Only applicable to a singleton bean.
|
||||
*/
|
||||
boolean isLazyInit();
|
||||
|
||||
/**
|
||||
* Set whether this bean should be lazily initialized.
|
||||
* <p>If <code>false</code>, the bean will get instantiated on startup by bean
|
||||
* factories that perform eager initialization of singletons.
|
||||
*/
|
||||
void setLazyInit(boolean lazyInit);
|
||||
|
||||
/**
|
||||
* Return the bean names that this bean depends on.
|
||||
*/
|
||||
String[] getDependsOn();
|
||||
|
||||
/**
|
||||
* Set the names of the beans that this bean depends on being initialized.
|
||||
* The bean factory will guarantee that these beans get initialized first.
|
||||
*/
|
||||
void setDependsOn(String[] dependsOn);
|
||||
|
||||
/**
|
||||
* Return whether this bean is a candidate for getting autowired into some other bean.
|
||||
*/
|
||||
@@ -153,6 +177,20 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
|
||||
*/
|
||||
void setAutowireCandidate(boolean autowireCandidate);
|
||||
|
||||
/**
|
||||
* Return whether this bean is a primary autowire candidate.
|
||||
* If this value is true for exactly one bean among multiple
|
||||
* matching candidates, it will serve as a tie-breaker.
|
||||
*/
|
||||
boolean isPrimary();
|
||||
|
||||
/**
|
||||
* Set whether this bean is a primary autowire candidate.
|
||||
* <p>If this value is true for exactly one bean among multiple
|
||||
* matching candidates, it will serve as a tie-breaker.
|
||||
*/
|
||||
void setPrimary(boolean primary);
|
||||
|
||||
|
||||
/**
|
||||
* Return the constructor argument values for this bean.
|
||||
@@ -180,12 +218,6 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
|
||||
*/
|
||||
boolean isAbstract();
|
||||
|
||||
/**
|
||||
* Return whether this bean should be lazily initialized, that is, not
|
||||
* eagerly instantiated on startup.
|
||||
*/
|
||||
boolean isLazyInit();
|
||||
|
||||
/**
|
||||
* Get the role hint for this <code>BeanDefinition</code>. The role hint
|
||||
* provides tools with an indication of the importance of a particular
|
||||
|
||||
@@ -524,7 +524,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
|
||||
@Override
|
||||
protected Class predictBeanType(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) {
|
||||
Class beanClass = null;
|
||||
Class beanClass;
|
||||
if (mbd.getFactoryMethodName() != null) {
|
||||
beanClass = getTypeForFactoryMethod(beanName, mbd, typesToMatch);
|
||||
}
|
||||
@@ -562,7 +562,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @see #createBean
|
||||
*/
|
||||
protected Class getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) {
|
||||
Class factoryClass = null;
|
||||
Class factoryClass;
|
||||
boolean isStatic = true;
|
||||
|
||||
String factoryBeanName = mbd.getFactoryBeanName();
|
||||
@@ -1203,7 +1203,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
|
||||
MutablePropertyValues mpvs = null;
|
||||
List<PropertyValue> original = null;
|
||||
List<PropertyValue> original;
|
||||
|
||||
if (pvs instanceof MutablePropertyValues) {
|
||||
mpvs = (MutablePropertyValues) pvs;
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
@@ -83,7 +83,10 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
* Constant that indicates determining an appropriate autowire strategy
|
||||
* through introspection of the bean class.
|
||||
* @see #setAutowireMode
|
||||
* @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,
|
||||
* use annotation-based autowiring for clearer demarcation of autowiring needs.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
|
||||
|
||||
|
||||
@@ -134,11 +137,11 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
|
||||
private boolean autowireCandidate = true;
|
||||
|
||||
private boolean primary = false;
|
||||
|
||||
private final Map<String, AutowireCandidateQualifier> qualifiers =
|
||||
new LinkedHashMap<String, AutowireCandidateQualifier>();
|
||||
|
||||
private boolean primary = false;
|
||||
|
||||
private ConstructorArgumentValues constructorArgumentValues;
|
||||
|
||||
private MutablePropertyValues propertyValues;
|
||||
@@ -317,8 +320,8 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
*/
|
||||
public void applyDefaults(BeanDefinitionDefaults defaults) {
|
||||
setLazyInit(defaults.isLazyInit());
|
||||
setDependencyCheck(defaults.getDependencyCheck());
|
||||
setAutowireMode(defaults.getAutowireMode());
|
||||
setDependencyCheck(defaults.getDependencyCheck());
|
||||
setInitMethodName(defaults.getInitMethodName());
|
||||
setEnforceInitMethod(false);
|
||||
setDestroyMethodName(defaults.getDestroyMethodName());
|
||||
@@ -336,7 +339,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
/**
|
||||
* Specify the class for this bean.
|
||||
*/
|
||||
public void setBeanClass(Class beanClass) {
|
||||
public void setBeanClass(Class<?> beanClass) {
|
||||
this.beanClass = beanClass;
|
||||
}
|
||||
|
||||
@@ -346,7 +349,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
* @throws IllegalStateException if the bean definition does not define a bean class,
|
||||
* or a specified bean class name has not been resolved into an actual Class
|
||||
*/
|
||||
public Class getBeanClass() throws IllegalStateException {
|
||||
public Class<?> getBeanClass() throws IllegalStateException {
|
||||
Object beanClassObject = this.beanClass;
|
||||
if (beanClassObject == null) {
|
||||
throw new IllegalStateException("No bean class specified on bean definition");
|
||||
@@ -556,7 +559,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
|
||||
/**
|
||||
* Set the names of the beans that this bean depends on being initialized.
|
||||
* The bean factory will guarantee that these beans get initialized before.
|
||||
* The bean factory will guarantee that these beans get initialized first.
|
||||
* <p>Note that dependencies are normally expressed through bean properties or
|
||||
* constructor arguments. This property should just be necessary for other kinds
|
||||
* of dependencies like statics (*ugh*) or database preparation on startup.
|
||||
@@ -586,6 +589,24 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
return this.autowireCandidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this bean is a primary autowire candidate.
|
||||
* If this value is true for exactly one bean among multiple
|
||||
* matching candidates, it will serve as a tie-breaker.
|
||||
*/
|
||||
public void setPrimary(boolean primary) {
|
||||
this.primary = primary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this bean is a primary autowire candidate.
|
||||
* If this value is true for exactly one bean among multiple
|
||||
* matching candidates, it will serve as a tie-breaker.
|
||||
*/
|
||||
public boolean isPrimary() {
|
||||
return this.primary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a qualifier to be used for autowire candidate resolution,
|
||||
* keyed by the qualifier's type name.
|
||||
@@ -626,24 +647,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
this.qualifiers.putAll(source.qualifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this bean is a primary autowire candidate.
|
||||
* If this value is true for exactly one bean among multiple
|
||||
* matching candidates, it will serve as a tie-breaker.
|
||||
*/
|
||||
public void setPrimary(boolean primary) {
|
||||
this.primary = primary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this bean is a primary autowire candidate.
|
||||
* If this value is true for exactly one bean among multiple
|
||||
* matching candidates, it will serve as a tie-breaker.
|
||||
*/
|
||||
public boolean isPrimary() {
|
||||
return this.primary;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specify constructor argument values for this bean.
|
||||
|
||||
@@ -59,6 +59,28 @@ abstract class AutowireUtils {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the given factory methods, preferring public methods and "greedy" ones
|
||||
* with a maximum of arguments. The result will contain public methods first,
|
||||
* with decreasing number of arguments, then non-public methods, again with
|
||||
* decreasing number of arguments.
|
||||
* @param factoryMethods the factory method array to sort
|
||||
*/
|
||||
public static void sortFactoryMethods(Method[] factoryMethods) {
|
||||
Arrays.sort(factoryMethods, new Comparator<Method>() {
|
||||
public int compare(Method fm1, Method fm2) {
|
||||
boolean p1 = Modifier.isPublic(fm1.getModifiers());
|
||||
boolean p2 = Modifier.isPublic(fm2.getModifiers());
|
||||
if (p1 != p2) {
|
||||
return (p1 ? -1 : 1);
|
||||
}
|
||||
int c1pl = fm1.getParameterTypes().length;
|
||||
int c2pl = fm2.getParameterTypes().length;
|
||||
return (new Integer(c1pl)).compareTo(c2pl) * -1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given bean property is excluded from dependency checks.
|
||||
* <p>This implementation excludes properties defined by CGLIB.
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
@@ -45,6 +46,7 @@ import org.springframework.core.MethodParameter;
|
||||
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.
|
||||
@@ -284,6 +286,10 @@ class ConstructorResolver {
|
||||
}
|
||||
else {
|
||||
// It's a static factory method on the bean class.
|
||||
if (!mbd.hasBeanClass()) {
|
||||
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
|
||||
"bean definition declares neither a bean class nor a factory-bean reference");
|
||||
}
|
||||
factoryBean = null;
|
||||
factoryClass = mbd.getBeanClass();
|
||||
isStatic = true;
|
||||
@@ -309,7 +315,18 @@ class ConstructorResolver {
|
||||
if (factoryMethodToUse == null) {
|
||||
// Need to determine the factory method...
|
||||
// Try all methods with this name to see if they match the given arguments.
|
||||
Method[] candidates = ReflectionUtils.getAllDeclaredMethods(factoryClass);
|
||||
factoryClass = ClassUtils.getUserClass(factoryClass);
|
||||
Method[] rawCandidates = ReflectionUtils.getAllDeclaredMethods(factoryClass);
|
||||
List<Method> candidateSet = new ArrayList<Method>();
|
||||
for (Method candidate : rawCandidates) {
|
||||
if (Modifier.isStatic(candidate.getModifiers()) == isStatic &&
|
||||
candidate.getName().equals(mbd.getFactoryMethodName())) {
|
||||
candidateSet.add(candidate);
|
||||
}
|
||||
}
|
||||
Method[] candidates = candidateSet.toArray(new Method[candidateSet.size()]);
|
||||
AutowireUtils.sortFactoryMethods(candidates);
|
||||
|
||||
boolean autowiring = (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
|
||||
int minTypeDiffWeight = Integer.MAX_VALUE;
|
||||
ConstructorArgumentValues resolvedValues = null;
|
||||
@@ -332,10 +349,7 @@ class ConstructorResolver {
|
||||
Method candidate = candidates[i];
|
||||
Class[] paramTypes = candidate.getParameterTypes();
|
||||
|
||||
if (Modifier.isStatic(candidate.getModifiers()) == isStatic &&
|
||||
candidate.getName().equals(mbd.getFactoryMethodName()) &&
|
||||
paramTypes.length >= minNrOfArgs) {
|
||||
|
||||
if (paramTypes.length >= minNrOfArgs) {
|
||||
ArgumentsHolder args;
|
||||
|
||||
if (resolvedValues != null) {
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
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;
|
||||
@@ -47,7 +49,9 @@ 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;
|
||||
|
||||
/**
|
||||
@@ -428,6 +432,32 @@ 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;
|
||||
}
|
||||
return getAutowireCandidateResolver().isAutowireCandidate(
|
||||
new BeanDefinitionHolder(mbd, beanName, getAliases(beanName)), descriptor);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -51,6 +52,8 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
|
||||
private final Set<String> externallyManagedDestroyMethods = Collections.synchronizedSet(new HashSet<String>());
|
||||
|
||||
volatile Method factoryMethodForIntrospection;
|
||||
|
||||
/** Package-visible field for caching the resolved constructor or factory method */
|
||||
volatile Object resolvedConstructorOrFactoryMethod;
|
||||
|
||||
@@ -218,6 +221,10 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
public Method getFactoryMethodForIntrospection() {
|
||||
return this.factoryMethodForIntrospection;
|
||||
}
|
||||
|
||||
|
||||
public void registerExternallyManagedConfigMember(Member configMember) {
|
||||
this.externallyManagedConfigMembers.add(configMember);
|
||||
|
||||
Reference in New Issue
Block a user