Merge branch '6.2.x'
# Conflicts: # spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java # spring-core/src/main/java/org/springframework/core/convert/TypeDescriptor.java
This commit is contained in:
commit
3fff3b8a6d
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
|
@ -40,10 +40,14 @@ import org.springframework.util.StringUtils;
|
|||
* (which the methods defined on the ListableBeanFactory interface don't,
|
||||
* in contrast to the methods defined on the BeanFactory interface).
|
||||
*
|
||||
* <p><b>NOTE:</b> It is generally preferable to use {@link ObjectProvider#stream()}
|
||||
* via {@link BeanFactory#getBeanProvider} instead of this utility class.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @since 04.07.2003
|
||||
* @see BeanFactory#getBeanProvider
|
||||
*/
|
||||
public abstract class BeanFactoryUtils {
|
||||
|
||||
|
@ -309,7 +313,7 @@ public abstract class BeanFactoryUtils {
|
|||
* 'replacing' beans by explicitly choosing the same bean name in a child factory;
|
||||
* the bean in the ancestor factory won't be visible then, not even for by-type lookups.
|
||||
* @param lbf the bean factory
|
||||
* @param type type of bean to match
|
||||
* @param type the type of bean to match
|
||||
* @return the Map of matching bean instances, or an empty Map if none
|
||||
* @throws BeansException if a bean could not be created
|
||||
* @see ListableBeanFactory#getBeansOfType(Class)
|
||||
|
@ -348,7 +352,7 @@ public abstract class BeanFactoryUtils {
|
|||
* 'replacing' beans by explicitly choosing the same bean name in a child factory;
|
||||
* the bean in the ancestor factory won't be visible then, not even for by-type lookups.
|
||||
* @param lbf the bean factory
|
||||
* @param type type of bean to match
|
||||
* @param type the type of bean to match
|
||||
* @param includeNonSingletons whether to include prototype or scoped beans too
|
||||
* or just singletons (also applies to FactoryBeans)
|
||||
* @param allowEagerInit whether to initialize <i>lazy-init singletons</i> and
|
||||
|
@ -396,7 +400,7 @@ public abstract class BeanFactoryUtils {
|
|||
* 'replacing' beans by explicitly choosing the same bean name in a child factory;
|
||||
* the bean in the ancestor factory won't be visible then, not even for by-type lookups.
|
||||
* @param lbf the bean factory
|
||||
* @param type type of bean to match
|
||||
* @param type the type of bean to match
|
||||
* @return the matching bean instance
|
||||
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
|
||||
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
|
||||
|
@ -426,7 +430,7 @@ public abstract class BeanFactoryUtils {
|
|||
* 'replacing' beans by explicitly choosing the same bean name in a child factory;
|
||||
* the bean in the ancestor factory won't be visible then, not even for by-type lookups.
|
||||
* @param lbf the bean factory
|
||||
* @param type type of bean to match
|
||||
* @param type the type of bean to match
|
||||
* @param includeNonSingletons whether to include prototype or scoped beans too
|
||||
* or just singletons (also applies to FactoryBeans)
|
||||
* @param allowEagerInit whether to initialize <i>lazy-init singletons</i> and
|
||||
|
@ -458,7 +462,7 @@ public abstract class BeanFactoryUtils {
|
|||
* <p>This version of {@code beanOfType} automatically includes
|
||||
* prototypes and FactoryBeans.
|
||||
* @param lbf the bean factory
|
||||
* @param type type of bean to match
|
||||
* @param type the type of bean to match
|
||||
* @return the matching bean instance
|
||||
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
|
||||
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
|
||||
|
@ -482,7 +486,7 @@ public abstract class BeanFactoryUtils {
|
|||
* only raw FactoryBeans will be checked (which doesn't require initialization
|
||||
* of each FactoryBean).
|
||||
* @param lbf the bean factory
|
||||
* @param type type of bean to match
|
||||
* @param type the type of bean to match
|
||||
* @param includeNonSingletons whether to include prototype or scoped beans too
|
||||
* or just singletons (also applies to FactoryBeans)
|
||||
* @param allowEagerInit whether to initialize <i>lazy-init singletons</i> and
|
||||
|
@ -530,7 +534,7 @@ public abstract class BeanFactoryUtils {
|
|||
|
||||
/**
|
||||
* Extract a unique bean for the given type from the given Map of matching beans.
|
||||
* @param type type of bean to match
|
||||
* @param type the type of bean to match
|
||||
* @param matchingBeans all matching beans found
|
||||
* @return the unique bean instance
|
||||
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
|
||||
|
|
|
@ -56,10 +56,13 @@ import org.springframework.core.OrderComparator;
|
|||
public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {
|
||||
|
||||
/**
|
||||
* A predicate for unfiltered type matches.
|
||||
* A predicate for unfiltered type matches, including non-default candidates
|
||||
* but still excluding non-autowire candidates when used on injection points.
|
||||
* @since 6.2.3
|
||||
* @see #stream(Predicate)
|
||||
* @see #orderedStream(Predicate)
|
||||
* @see org.springframework.beans.factory.config.BeanDefinition#isAutowireCandidate()
|
||||
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#isDefaultCandidate()
|
||||
*/
|
||||
Predicate<Class<?>> UNFILTERED = (clazz -> true);
|
||||
|
||||
|
@ -209,7 +212,7 @@ public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {
|
|||
* without specific ordering guarantees (but typically in registration order).
|
||||
* <p>Note: The result may be filtered by default according to qualifiers on the
|
||||
* injection point versus target beans and the general autowire candidate status
|
||||
* of matching beans. For custom filtering against the raw type matches, use
|
||||
* of matching beans. For custom filtering against type-matching candidates, use
|
||||
* {@link #stream(Predicate)} instead (potentially with {@link #UNFILTERED}).
|
||||
* @since 5.1
|
||||
* @see #iterator()
|
||||
|
@ -234,7 +237,7 @@ public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {
|
|||
* if necessary.
|
||||
* <p>Note: The result may be filtered by default according to qualifiers on the
|
||||
* injection point versus target beans and the general autowire candidate status
|
||||
* of matching beans. For custom filtering against the raw type matches, use
|
||||
* of matching beans. For custom filtering against type-matching candidates, use
|
||||
* {@link #stream(Predicate)} instead (potentially with {@link #UNFILTERED}).
|
||||
* @since 5.1
|
||||
* @see #stream()
|
||||
|
|
|
@ -35,7 +35,9 @@ import java.util.Set;
|
|||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.config.TypedStringValue;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
@ -260,6 +262,24 @@ abstract class AutowireUtils {
|
|||
return method.getReturnType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the autowire-candidate status for the specified bean.
|
||||
* @param beanFactory the bean factory
|
||||
* @param beanName the name of the bean to check
|
||||
* @return whether the specified bean qualifies as an autowire candidate
|
||||
* @since 6.2.3
|
||||
* @see org.springframework.beans.factory.config.BeanDefinition#isAutowireCandidate()
|
||||
*/
|
||||
public static boolean isAutowireCandidate(ConfigurableBeanFactory beanFactory, String beanName) {
|
||||
try {
|
||||
return beanFactory.getMergedBeanDefinition(beanName).isAutowireCandidate();
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// A manually registered singleton instance not backed by a BeanDefinition.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reflective {@link InvocationHandler} for lazy access to the current target object.
|
||||
|
|
|
@ -2480,6 +2480,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
@Override
|
||||
public Stream<Object> stream(Predicate<Class<?>> customFilter) {
|
||||
return Arrays.stream(getBeanNamesForTypedStream(this.descriptor.getResolvableType(), true))
|
||||
.filter(name -> AutowireUtils.isAutowireCandidate(DefaultListableBeanFactory.this, name))
|
||||
.filter(name -> customFilter.test(getType(name)))
|
||||
.map(name -> getBean(name))
|
||||
.filter(bean -> !(bean instanceof NullBean));
|
||||
|
@ -2493,7 +2494,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
}
|
||||
Map<String, Object> matchingBeans = CollectionUtils.newLinkedHashMap(beanNames.length);
|
||||
for (String beanName : beanNames) {
|
||||
if (customFilter.test(getType(beanName))) {
|
||||
if (AutowireUtils.isAutowireCandidate(DefaultListableBeanFactory.this, beanName) &&
|
||||
customFilter.test(getType(beanName))) {
|
||||
Object beanInstance = getBean(beanName);
|
||||
if (!(beanInstance instanceof NullBean)) {
|
||||
matchingBeans.put(beanName, beanInstance);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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,10 +16,13 @@
|
|||
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
|
||||
/**
|
||||
* {@link AutowireCandidateResolver} implementation to use when no annotation
|
||||
|
@ -37,42 +40,6 @@ public class SimpleAutowireCandidateResolver implements AutowireCandidateResolve
|
|||
*/
|
||||
public static final SimpleAutowireCandidateResolver INSTANCE = new SimpleAutowireCandidateResolver();
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
|
||||
return bdHolder.getBeanDefinition().isAutowireCandidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRequired(DependencyDescriptor descriptor) {
|
||||
return descriptor.isRequired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasQualifier(DependencyDescriptor descriptor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getSuggestedName(DependencyDescriptor descriptor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Object getSuggestedValue(DependencyDescriptor descriptor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Class<?> getLazyResolutionProxyClass(DependencyDescriptor descriptor, @Nullable String beanName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation returns {@code this} as-is.
|
||||
* @see #INSTANCE
|
||||
|
@ -82,4 +49,31 @@ public class SimpleAutowireCandidateResolver implements AutowireCandidateResolve
|
|||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolve a map of all beans of the given type, also picking up beans defined in
|
||||
* ancestor bean factories, with the specific condition that each bean actually
|
||||
* has autowire candidate status. This matches simple injection point resolution
|
||||
* as implemented by this {@link AutowireCandidateResolver} strategy, including
|
||||
* beans which are not marked as default candidates but excluding beans which
|
||||
* are not even marked as autowire candidates.
|
||||
* @param lbf the bean factory
|
||||
* @param type the type of bean to match
|
||||
* @return the Map of matching bean instances, or an empty Map if none
|
||||
* @throws BeansException if a bean could not be created
|
||||
* @since 6.2.3
|
||||
* @see BeanFactoryUtils#beansOfTypeIncludingAncestors(ListableBeanFactory, Class)
|
||||
* @see org.springframework.beans.factory.config.BeanDefinition#isAutowireCandidate()
|
||||
* @see AbstractBeanDefinition#isDefaultCandidate()
|
||||
*/
|
||||
public static <T> Map<String, T> resolveAutowireCandidates(ConfigurableListableBeanFactory lbf, Class<T> type) {
|
||||
Map<String, T> candidates = new LinkedHashMap<>();
|
||||
for (String beanName : BeanFactoryUtils.beanNamesForTypeIncludingAncestors(lbf, type)) {
|
||||
if (AutowireUtils.isAutowireCandidate(lbf, beanName)) {
|
||||
candidates.put(beanName, lbf.getBean(beanName, type));
|
||||
}
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ import org.mockito.Mockito;
|
|||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
|
@ -65,6 +66,7 @@ import org.springframework.beans.factory.support.AutowireCandidateQualifier;
|
|||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.support.SimpleAutowireCandidateResolver;
|
||||
import org.springframework.beans.testfixture.beans.DerivedTestBean;
|
||||
import org.springframework.beans.testfixture.beans.ITestBean;
|
||||
import org.springframework.beans.testfixture.beans.IndexedTestBean;
|
||||
|
@ -1756,14 +1758,17 @@ class AutowiredAnnotationBeanPostProcessorTests {
|
|||
RootBeanDefinition tb2 = new RootBeanDefinition(TestBeanFactory.class);
|
||||
tb2.setFactoryMethodName("newTestBean2");
|
||||
bf.registerBeanDefinition("testBean2", tb2);
|
||||
|
||||
DefaultListableBeanFactory parent = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition tb3 = new RootBeanDefinition(TestBean.class);
|
||||
tb3.setAutowireCandidate(false);
|
||||
tb3.setLazyInit(true);
|
||||
bf.registerBeanDefinition("testBean3", tb3);
|
||||
parent.registerBeanDefinition("testBean3", tb3);
|
||||
RootBeanDefinition tb4 = new RootBeanDefinition(DerivedTestBean.class);
|
||||
tb4.setDefaultCandidate(false);
|
||||
tb4.setLazyInit(true);
|
||||
bf.registerBeanDefinition("testBean4", tb4);
|
||||
parent.registerBeanDefinition("testBean4", tb4);
|
||||
bf.setParentBeanFactory(parent);
|
||||
|
||||
ObjectProviderInjectionBean bean = bf.getBean("annotatedBean", ObjectProviderInjectionBean.class);
|
||||
assertThat(bean.streamTestBeans()).containsExactly(bf.getBean("testBean1", TestBean.class),
|
||||
|
@ -1772,16 +1777,19 @@ class AutowiredAnnotationBeanPostProcessorTests {
|
|||
bf.getBean("testBean1", TestBean.class));
|
||||
assertThat(bf.containsSingleton("testBean3")).isFalse();
|
||||
assertThat(bean.plainTestBeans()).containsExactly(bf.getBean("testBean1", TestBean.class),
|
||||
bf.getBean("testBean2", TestBean.class), bf.getBean("testBean3", TestBean.class));
|
||||
bf.getBean("testBean2", TestBean.class));
|
||||
assertThat(bean.plainTestBeansInOrder()).containsExactly(bf.getBean("testBean2", TestBean.class),
|
||||
bf.getBean("testBean1", TestBean.class), bf.getBean("testBean3", TestBean.class));
|
||||
bf.getBean("testBean1", TestBean.class));
|
||||
assertThat(bf.containsSingleton("testBean4")).isFalse();
|
||||
assertThat(bean.allTestBeans()).containsExactly(bf.getBean("testBean1", TestBean.class),
|
||||
bf.getBean("testBean2", TestBean.class), bf.getBean("testBean3", TestBean.class),
|
||||
bf.getBean("testBean4", TestBean.class));
|
||||
bf.getBean("testBean2", TestBean.class), bf.getBean("testBean4", TestBean.class));
|
||||
assertThat(bean.allTestBeansInOrder()).containsExactly(bf.getBean("testBean2", TestBean.class),
|
||||
bf.getBean("testBean1", TestBean.class), bf.getBean("testBean3", TestBean.class),
|
||||
bf.getBean("testBean4", TestBean.class));
|
||||
bf.getBean("testBean1", TestBean.class), bf.getBean("testBean4", TestBean.class));
|
||||
|
||||
Map<String, TestBean> typeMatches = BeanFactoryUtils.beansOfTypeIncludingAncestors(bf, TestBean.class);
|
||||
assertThat(typeMatches.remove("testBean3")).isNotNull();
|
||||
Map<String, TestBean> candidates = SimpleAutowireCandidateResolver.resolveAutowireCandidates(bf, TestBean.class);
|
||||
assertThat(candidates).containsExactlyEntriesOf(candidates);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.Arrays;
|
|||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
@ -71,7 +72,9 @@ public class TypeDescriptor implements Serializable {
|
|||
|
||||
private final ResolvableType resolvableType;
|
||||
|
||||
private final AnnotatedElementAdapter annotatedElement;
|
||||
private final AnnotatedElementSupplier annotatedElementSupplier;
|
||||
|
||||
private volatile @Nullable AnnotatedElementAdapter annotatedElement;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -83,7 +86,7 @@ public class TypeDescriptor implements Serializable {
|
|||
public TypeDescriptor(MethodParameter methodParameter) {
|
||||
this.resolvableType = ResolvableType.forMethodParameter(methodParameter);
|
||||
this.type = this.resolvableType.resolve(methodParameter.getNestedParameterType());
|
||||
this.annotatedElement = AnnotatedElementAdapter.from(methodParameter.getParameterIndex() == -1 ?
|
||||
this.annotatedElementSupplier = () -> AnnotatedElementAdapter.from(methodParameter.getParameterIndex() == -1 ?
|
||||
methodParameter.getMethodAnnotations() : methodParameter.getParameterAnnotations());
|
||||
}
|
||||
|
||||
|
@ -95,7 +98,7 @@ public class TypeDescriptor implements Serializable {
|
|||
public TypeDescriptor(Field field) {
|
||||
this.resolvableType = ResolvableType.forField(field);
|
||||
this.type = this.resolvableType.resolve(field.getType());
|
||||
this.annotatedElement = AnnotatedElementAdapter.from(field.getAnnotations());
|
||||
this.annotatedElementSupplier = () -> AnnotatedElementAdapter.from(field.getAnnotations());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,7 +111,7 @@ public class TypeDescriptor implements Serializable {
|
|||
Assert.notNull(property, "Property must not be null");
|
||||
this.resolvableType = ResolvableType.forMethodParameter(property.getMethodParameter());
|
||||
this.type = this.resolvableType.resolve(property.getType());
|
||||
this.annotatedElement = AnnotatedElementAdapter.from(property.getAnnotations());
|
||||
this.annotatedElementSupplier = () -> AnnotatedElementAdapter.from(property.getAnnotations());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,7 +127,7 @@ public class TypeDescriptor implements Serializable {
|
|||
public TypeDescriptor(ResolvableType resolvableType, @Nullable Class<?> type, Annotation @Nullable [] annotations) {
|
||||
this.resolvableType = resolvableType;
|
||||
this.type = (type != null ? type : resolvableType.toClass());
|
||||
this.annotatedElement = AnnotatedElementAdapter.from(annotations);
|
||||
this.annotatedElementSupplier = () -> AnnotatedElementAdapter.from(annotations);
|
||||
}
|
||||
|
||||
|
||||
|
@ -249,12 +252,21 @@ public class TypeDescriptor implements Serializable {
|
|||
return getType().isPrimitive();
|
||||
}
|
||||
|
||||
private AnnotatedElementAdapter getAnnotatedElement() {
|
||||
AnnotatedElementAdapter annotatedElement = this.annotatedElement;
|
||||
if (annotatedElement == null) {
|
||||
annotatedElement = this.annotatedElementSupplier.get();
|
||||
this.annotatedElement = annotatedElement;
|
||||
}
|
||||
return annotatedElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the annotations associated with this type descriptor, if any.
|
||||
* @return the annotations, or an empty array if none
|
||||
*/
|
||||
public Annotation[] getAnnotations() {
|
||||
return this.annotatedElement.getAnnotations();
|
||||
return getAnnotatedElement().getAnnotations();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -265,12 +277,13 @@ public class TypeDescriptor implements Serializable {
|
|||
* @return {@code true} if the annotation is present
|
||||
*/
|
||||
public boolean hasAnnotation(Class<? extends Annotation> annotationType) {
|
||||
if (this.annotatedElement.isEmpty()) {
|
||||
AnnotatedElementAdapter annotatedElement = getAnnotatedElement();
|
||||
if (annotatedElement.isEmpty()) {
|
||||
// Shortcut: AnnotatedElementUtils would have to expect AnnotatedElement.getAnnotations()
|
||||
// to return a copy of the array, whereas we can do it more efficiently here.
|
||||
return false;
|
||||
}
|
||||
return AnnotatedElementUtils.isAnnotated(this.annotatedElement, annotationType);
|
||||
return AnnotatedElementUtils.isAnnotated(annotatedElement, annotationType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -280,12 +293,13 @@ public class TypeDescriptor implements Serializable {
|
|||
* @return the annotation, or {@code null} if no such annotation exists on this type descriptor
|
||||
*/
|
||||
public <T extends Annotation> @Nullable T getAnnotation(Class<T> annotationType) {
|
||||
if (this.annotatedElement.isEmpty()) {
|
||||
AnnotatedElementAdapter annotatedElement = getAnnotatedElement();
|
||||
if (annotatedElement.isEmpty()) {
|
||||
// Shortcut: AnnotatedElementUtils would have to expect AnnotatedElement.getAnnotations()
|
||||
// to return a copy of the array, whereas we can do it more efficiently here.
|
||||
return null;
|
||||
}
|
||||
return AnnotatedElementUtils.getMergedAnnotation(this.annotatedElement, annotationType);
|
||||
return AnnotatedElementUtils.getMergedAnnotation(annotatedElement, annotationType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -792,4 +806,8 @@ public class TypeDescriptor implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private interface AnnotatedElementSupplier extends Supplier<AnnotatedElementAdapter>, Serializable {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue