|
|
|
@ -17,6 +17,7 @@ |
|
|
|
package org.springframework.beans.factory.annotation; |
|
|
|
package org.springframework.beans.factory.annotation; |
|
|
|
|
|
|
|
|
|
|
|
import java.beans.PropertyDescriptor; |
|
|
|
import java.beans.PropertyDescriptor; |
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
import java.lang.annotation.Annotation; |
|
|
|
import java.lang.annotation.Annotation; |
|
|
|
import java.lang.reflect.AccessibleObject; |
|
|
|
import java.lang.reflect.AccessibleObject; |
|
|
|
import java.lang.reflect.Constructor; |
|
|
|
import java.lang.reflect.Constructor; |
|
|
|
@ -62,6 +63,10 @@ import org.springframework.core.annotation.AnnotationAttributes; |
|
|
|
import org.springframework.core.annotation.AnnotationUtils; |
|
|
|
import org.springframework.core.annotation.AnnotationUtils; |
|
|
|
import org.springframework.core.annotation.MergedAnnotation; |
|
|
|
import org.springframework.core.annotation.MergedAnnotation; |
|
|
|
import org.springframework.core.annotation.MergedAnnotations; |
|
|
|
import org.springframework.core.annotation.MergedAnnotations; |
|
|
|
|
|
|
|
import org.springframework.core.type.AnnotationMetadata; |
|
|
|
|
|
|
|
import org.springframework.core.type.MethodMetadata; |
|
|
|
|
|
|
|
import org.springframework.core.type.classreading.MetadataReaderFactory; |
|
|
|
|
|
|
|
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory; |
|
|
|
import org.springframework.lang.Nullable; |
|
|
|
import org.springframework.lang.Nullable; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
import org.springframework.util.ClassUtils; |
|
|
|
import org.springframework.util.ClassUtils; |
|
|
|
@ -144,6 +149,9 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA |
|
|
|
@Nullable |
|
|
|
@Nullable |
|
|
|
private ConfigurableListableBeanFactory beanFactory; |
|
|
|
private ConfigurableListableBeanFactory beanFactory; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Nullable |
|
|
|
|
|
|
|
private MetadataReaderFactory metadataReaderFactory; |
|
|
|
|
|
|
|
|
|
|
|
private final Set<String> lookupMethodsChecked = Collections.newSetFromMap(new ConcurrentHashMap<>(256)); |
|
|
|
private final Set<String> lookupMethodsChecked = Collections.newSetFromMap(new ConcurrentHashMap<>(256)); |
|
|
|
|
|
|
|
|
|
|
|
private final Map<Class<?>, Constructor<?>[]> candidateConstructorsCache = new ConcurrentHashMap<>(256); |
|
|
|
private final Map<Class<?>, Constructor<?>[]> candidateConstructorsCache = new ConcurrentHashMap<>(256); |
|
|
|
@ -238,6 +246,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA |
|
|
|
"AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory: " + beanFactory); |
|
|
|
"AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory: " + beanFactory); |
|
|
|
} |
|
|
|
} |
|
|
|
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; |
|
|
|
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; |
|
|
|
|
|
|
|
this.metadataReaderFactory = new SimpleMetadataReaderFactory(this.beanFactory.getBeanClassLoader()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -463,12 +472,11 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA |
|
|
|
return InjectionMetadata.EMPTY; |
|
|
|
return InjectionMetadata.EMPTY; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); |
|
|
|
final List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); |
|
|
|
Class<?> targetClass = clazz; |
|
|
|
Class<?> targetClass = clazz; |
|
|
|
|
|
|
|
|
|
|
|
do { |
|
|
|
do { |
|
|
|
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); |
|
|
|
final List<InjectionMetadata.InjectedElement> fieldElements = new ArrayList<>(); |
|
|
|
|
|
|
|
|
|
|
|
ReflectionUtils.doWithLocalFields(targetClass, field -> { |
|
|
|
ReflectionUtils.doWithLocalFields(targetClass, field -> { |
|
|
|
MergedAnnotation<?> ann = findAutowiredAnnotation(field); |
|
|
|
MergedAnnotation<?> ann = findAutowiredAnnotation(field); |
|
|
|
if (ann != null) { |
|
|
|
if (ann != null) { |
|
|
|
@ -479,10 +487,11 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
boolean required = determineRequiredStatus(ann); |
|
|
|
boolean required = determineRequiredStatus(ann); |
|
|
|
currElements.add(new AutowiredFieldElement(field, required)); |
|
|
|
fieldElements.add(new AutowiredFieldElement(field, required)); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final List<InjectionMetadata.InjectedElement> methodElements = new ArrayList<>(); |
|
|
|
ReflectionUtils.doWithLocalMethods(targetClass, method -> { |
|
|
|
ReflectionUtils.doWithLocalMethods(targetClass, method -> { |
|
|
|
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); |
|
|
|
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); |
|
|
|
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { |
|
|
|
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { |
|
|
|
@ -504,11 +513,12 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA |
|
|
|
} |
|
|
|
} |
|
|
|
boolean required = determineRequiredStatus(ann); |
|
|
|
boolean required = determineRequiredStatus(ann); |
|
|
|
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); |
|
|
|
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); |
|
|
|
currElements.add(new AutowiredMethodElement(method, required, pd)); |
|
|
|
methodElements.add(new AutowiredMethodElement(method, required, pd)); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
elements.addAll(0, currElements); |
|
|
|
elements.addAll(0, sortMethodElements(methodElements, targetClass)); |
|
|
|
|
|
|
|
elements.addAll(0, fieldElements); |
|
|
|
targetClass = targetClass.getSuperclass(); |
|
|
|
targetClass = targetClass.getSuperclass(); |
|
|
|
} |
|
|
|
} |
|
|
|
while (targetClass != null && targetClass != Object.class); |
|
|
|
while (targetClass != null && targetClass != Object.class); |
|
|
|
@ -573,6 +583,47 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA |
|
|
|
return BeanFactoryUtils.beansOfTypeIncludingAncestors(this.beanFactory, type); |
|
|
|
return BeanFactoryUtils.beansOfTypeIncludingAncestors(this.beanFactory, type); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Sort the method elements via ASM for deterministic declaration order if possible. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
private List<InjectionMetadata.InjectedElement> sortMethodElements( |
|
|
|
|
|
|
|
List<InjectionMetadata.InjectedElement> methodElements, Class<?> targetClass) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (this.metadataReaderFactory != null && methodElements.size() > 1) { |
|
|
|
|
|
|
|
// Try reading the class file via ASM for deterministic declaration order...
|
|
|
|
|
|
|
|
// Unfortunately, the JVM's standard reflection returns methods in arbitrary
|
|
|
|
|
|
|
|
// order, even between different runs of the same application on the same JVM.
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
AnnotationMetadata asm = |
|
|
|
|
|
|
|
this.metadataReaderFactory.getMetadataReader(targetClass.getName()).getAnnotationMetadata(); |
|
|
|
|
|
|
|
Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Autowired.class.getName()); |
|
|
|
|
|
|
|
if (asmMethods.size() >= methodElements.size()) { |
|
|
|
|
|
|
|
List<InjectionMetadata.InjectedElement> candidateMethods = new ArrayList<>(methodElements); |
|
|
|
|
|
|
|
List<InjectionMetadata.InjectedElement> selectedMethods = new ArrayList<>(asmMethods.size()); |
|
|
|
|
|
|
|
for (MethodMetadata asmMethod : asmMethods) { |
|
|
|
|
|
|
|
for (Iterator<InjectionMetadata.InjectedElement> it = candidateMethods.iterator(); it.hasNext();) { |
|
|
|
|
|
|
|
InjectionMetadata.InjectedElement element = it.next(); |
|
|
|
|
|
|
|
if (element.getMember().getName().equals(asmMethod.getMethodName())) { |
|
|
|
|
|
|
|
selectedMethods.add(element); |
|
|
|
|
|
|
|
it.remove(); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (selectedMethods.size() == methodElements.size()) { |
|
|
|
|
|
|
|
// All reflection-detected methods found in ASM method set -> proceed
|
|
|
|
|
|
|
|
return selectedMethods; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (IOException ex) { |
|
|
|
|
|
|
|
logger.debug("Failed to read class file via ASM for determining @Autowired method order", ex); |
|
|
|
|
|
|
|
// No worries, let's continue with the reflection metadata we started with...
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return methodElements; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Register the specified bean as dependent on the autowired beans. |
|
|
|
* Register the specified bean as dependent on the autowired beans. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|