Retain support for legacy PostConstruct/PreDestroy/Inject variants

Also removes JAX-WS support from CommonAnnotationBeanPostProcessor.

Closes gh-27444
See gh-27422
This commit is contained in:
Juergen Hoeller 2021-09-21 17:07:42 +02:00
parent 6976bf774b
commit 774583dfa7
7 changed files with 92 additions and 183 deletions

View File

@ -230,7 +230,6 @@ configure(allprojects) { project ->
dependency "jakarta.validation:jakarta.validation-api:3.0.0"
dependency "jakarta.websocket:jakarta.websocket-api:2.0.0"
dependency "jakarta.xml.bind:jakarta.xml.bind-api:3.0.1"
dependency "jakarta.xml.ws:jakarta.xml.ws-api:3.0.1"
dependency "com.sun.activation:jakarta.activation:2.0.1"
dependency "com.sun.mail:jakarta.mail:2.0.1"

View File

@ -75,8 +75,10 @@ import org.springframework.util.StringUtils;
* by default, Spring's {@link Autowired @Autowired} and {@link Value @Value}
* annotations.
*
* <p>Also supports JSR-330's {@link jakarta.inject.Inject @Inject} annotation,
* <p>Also supports the common {@link jakarta.inject.Inject @Inject} annotation,
* if available, as a direct alternative to Spring's own {@code @Autowired}.
* Additionally, it retains support for the {@code javax.inject.Inject} variant
* dating back to the original JSR-330 specification (as known from Java EE 6-8).
*
* <h3>Autowired Constructors</h3>
* <p>Only one constructor of any given bean class may declare this annotation with
@ -154,20 +156,30 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
/**
* Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's
* standard {@link Autowired @Autowired} and {@link Value @Value} annotations.
* <p>Also supports JSR-330's {@link jakarta.inject.Inject @Inject} annotation,
* if available.
* <p>Also supports the common {@link jakarta.inject.Inject @Inject} annotation,
* if available, as well as the original {@code javax.inject.Inject} variant.
*/
@SuppressWarnings("unchecked")
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("jakarta.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'jakarta.inject.Inject' annotation found and supported for autowiring");
logger.trace("'jakarta.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
// jakarta.inject API not available - simply skip.
}
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// javax.inject API not available - simply skip.
}
}
@ -177,7 +189,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
* setter methods, and arbitrary config methods.
* <p>The default autowired annotation types are the Spring-provided
* {@link Autowired @Autowired} and {@link Value @Value} annotations as well
* as JSR-330's {@link jakarta.inject.Inject @Inject} annotation, if available.
* as the common {@code @Inject} annotation, if available.
* <p>This setter property exists so that developers can provide their own
* (non-Spring-specific) annotation type to indicate that a member is supposed
* to be autowired.
@ -193,7 +205,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
* setter methods, and arbitrary config methods.
* <p>The default autowired annotation types are the Spring-provided
* {@link Autowired @Autowired} and {@link Value @Value} annotations as well
* as JSR-330's {@link jakarta.inject.Inject @Inject} annotation, if available.
* as the common {@code @Inject} annotation, if available.
* <p>This setter property exists so that developers can provide their own
* (non-Spring-specific) annotation types to indicate that a member is supposed
* to be autowired.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 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.
@ -66,7 +66,7 @@ import org.springframework.util.ReflectionUtils;
* init method and destroy method, respectively.
*
* <p>Spring's {@link org.springframework.context.annotation.CommonAnnotationBeanPostProcessor}
* supports the JSR-250 {@link jakarta.annotation.PostConstruct} and {@link jakarta.annotation.PreDestroy}
* supports the {@link jakarta.annotation.PostConstruct} and {@link jakarta.annotation.PreDestroy}
* annotations out of the box, as init annotation and destroy annotation, respectively.
* Furthermore, it also supports the {@link jakarta.annotation.Resource} annotation
* for annotation-driven injection of named beans.
@ -117,7 +117,7 @@ public class InitDestroyAnnotationBeanPostProcessor
* methods to call after configuration of a bean.
* <p>Any custom annotation can be used, since there are no required
* annotation attributes. There is no default, although a typical choice
* is the JSR-250 {@link jakarta.annotation.PostConstruct} annotation.
* is the {@link jakarta.annotation.PostConstruct} annotation.
*/
public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) {
this.initAnnotationType = initAnnotationType;
@ -128,7 +128,7 @@ public class InitDestroyAnnotationBeanPostProcessor
* methods to call when the context is shutting down.
* <p>Any custom annotation can be used, since there are no required
* annotation attributes. There is no default, although a typical choice
* is the JSR-250 {@link jakarta.annotation.PreDestroy} annotation.
* is the {@link jakarta.annotation.PreDestroy} annotation.
*/
public void setDestroyAnnotationType(Class<? extends Annotation> destroyAnnotationType) {
this.destroyAnnotationType = destroyAnnotationType;

View File

@ -14,9 +14,8 @@ dependencies {
optional("jakarta.enterprise.concurrent:jakarta.enterprise.concurrent-api")
optional("jakarta.inject:jakarta.inject-api")
optional("jakarta.interceptor:jakarta.interceptor-api")
optional("javax.money:money-api")
optional("jakarta.validation:jakarta.validation-api")
optional("jakarta.xml.ws:jakarta.xml.ws-api")
optional("javax.money:money-api")
optional("org.aspectj:aspectjweaver")
optional("org.codehaus.groovy:groovy")
optional("org.apache-extras.beanshell:bsh")
@ -32,8 +31,8 @@ dependencies {
testImplementation("org.codehaus.groovy:groovy-test")
testImplementation("org.codehaus.groovy:groovy-xml")
testImplementation("org.apache.commons:commons-pool2")
testImplementation("jakarta.inject:jakarta.inject-tck")
testImplementation("org.awaitility:awaitility")
testImplementation("jakarta.inject:jakarta.inject-tck")
testRuntimeOnly("jakarta.xml.bind:jakarta.xml.bind-api")
testRuntimeOnly("org.glassfish:jakarta.el")
// Substitute for javax.management:jmxremote_optional:1.0.1_04 (not available on Maven Central)

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2021 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.
@ -23,6 +23,7 @@ import java.util.Set;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@ -91,11 +92,17 @@ public abstract class AnnotationConfigUtils {
"org.springframework.context.annotation.internalRequiredAnnotationProcessor";
/**
* The bean name of the internally managed JSR-250 annotation processor.
* The bean name of the internally managed common annotation processor.
*/
public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalCommonAnnotationProcessor";
/**
* The bean name of the internally managed JSR-250 annotation processor.
*/
private static final String JSR250_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalJsr250AnnotationProcessor";
/**
* The bean name of the internally managed JPA annotation processor.
*/
@ -117,16 +124,18 @@ public abstract class AnnotationConfigUtils {
public static final String EVENT_LISTENER_FACTORY_BEAN_NAME =
"org.springframework.context.event.internalEventListenerFactory";
private static final boolean jsr250Present;
private static final boolean jpaPresent;
private static final ClassLoader classLoader = AnnotationConfigUtils.class.getClassLoader();
static {
ClassLoader classLoader = AnnotationConfigUtils.class.getClassLoader();
jsr250Present = ClassUtils.isPresent("jakarta.annotation.Resource", classLoader);
jpaPresent = ClassUtils.isPresent("jakarta.persistence.EntityManagerFactory", classLoader) &&
ClassUtils.isPresent(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, classLoader);
}
private static final boolean jakartaAnnotationsPresent =
ClassUtils.isPresent("jakarta.annotation.PostConstruct", classLoader);
private static final boolean jsr250Present =
ClassUtils.isPresent("javax.annotation.PostConstruct", classLoader);
private static final boolean jpaPresent =
ClassUtils.isPresent("jakarta.persistence.EntityManagerFactory", classLoader) &&
ClassUtils.isPresent(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, classLoader);
/**
@ -172,13 +181,28 @@ public abstract class AnnotationConfigUtils {
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// Check for Jakarta Annotations support, and if present add the CommonAnnotationBeanPostProcessor.
if (jakartaAnnotationsPresent && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add an InitDestroyAnnotationBeanPostProcessor
// for the javax variant of PostConstruct/PreDestroy.
if (jsr250Present && !registry.containsBeanDefinition(JSR250_ANNOTATION_PROCESSOR_BEAN_NAME)) {
try {
RootBeanDefinition def = new RootBeanDefinition(InitDestroyAnnotationBeanPostProcessor.class);
def.getPropertyValues().add("initAnnotationType", classLoader.loadClass("javax.annotation.PostConstruct"));
def.getPropertyValues().add("destroyAnnotationType", classLoader.loadClass("javax.annotation.PreDestroy"));
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, JSR250_ANNOTATION_PROCESSOR_BEAN_NAME));
}
catch (ClassNotFoundException ex) {
// Failed to load javax variants of the annotation types -> ignore.
}
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@ -21,13 +21,10 @@ import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@ -37,15 +34,10 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.xml.namespace.QName;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.annotation.Resource;
import jakarta.ejb.EJB;
import jakarta.xml.ws.Service;
import jakarta.xml.ws.WebServiceClient;
import jakarta.xml.ws.WebServiceRef;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.ProxyFactory;
@ -77,10 +69,9 @@ import org.springframework.util.StringValueResolver;
/**
* {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
* that supports common Java annotations out of the box, in particular the JSR-250
* that supports common Java annotations out of the box, in particular the common
* annotations in the {@code jakarta.annotation} package. These common Java
* annotations are supported in many Jakarta EE technologies (e.g. JSF 1.2),
* as well as in Java 6's JAX-WS.
* annotations are supported in many Jakarta EE technologies (e.g. JSF and JAX-RS).
*
* <p>This post-processor includes support for the {@link jakarta.annotation.PostConstruct}
* and {@link jakarta.annotation.PreDestroy} annotations - as init annotation
@ -95,12 +86,8 @@ import org.springframework.util.StringValueResolver;
* and default names as well. The target beans can be simple POJOs, with no special
* requirements other than the type having to match.
*
* <p>The JAX-WS {@link javax.xml.ws.WebServiceRef} annotation is supported too,
* analogous to {@link jakarta.annotation.Resource} but with the capability of creating
* specific JAX-WS service endpoints. This may either point to an explicitly defined
* resource by name or operate on a locally specified JAX-WS service class. Finally,
* this post-processor also supports the EJB 3 {@link jakarta.ejb.EJB} annotation,
* analogous to {@link jakarta.annotation.Resource} as well, with the capability to
* <p>This post-processor also supports the EJB 3 {@link jakarta.ejb.EJB} annotation,
* analogous to {@link jakarta.annotation.Resource}, with the capability to
* specify both a local bean name and a global JNDI name for fallback retrieval.
* The target beans can be plain POJOs as well as EJB 3 Session Beans in this case.
*
@ -143,22 +130,15 @@ import org.springframework.util.StringValueResolver;
public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor
implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {
@Nullable
private static final Class<? extends Annotation> webServiceRefClass;
private static final Set<Class<? extends Annotation>> resourceAnnotationTypes = new LinkedHashSet<>(4);
@Nullable
private static final Class<? extends Annotation> ejbClass;
private static final Set<Class<? extends Annotation>> resourceAnnotationTypes = new LinkedHashSet<>(4);
static {
webServiceRefClass = loadAnnotationType("javax.xml.ws.WebServiceRef");
ejbClass = loadAnnotationType("jakarta.ejb.EJB");
resourceAnnotationTypes.add(Resource.class);
if (webServiceRefClass != null) {
resourceAnnotationTypes.add(webServiceRefClass);
}
ejbClass = loadAnnotationType("jakarta.ejb.EJB");
if (ejbClass != null) {
resourceAnnotationTypes.add(ejbClass);
}
@ -195,15 +175,11 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
}
/**
* Ignore the given resource type when resolving {@code @Resource}
* annotations.
* <p>By default, the {@code javax.xml.ws.WebServiceContext} interface
* will be ignored, since it will be resolved by the JAX-WS runtime.
* Ignore the given resource type when resolving {@code @Resource} annotations.
* @param resourceType the resource type to ignore
*/
public void ignoreResourceType(String resourceType) {
@ -361,13 +337,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
ReflectionUtils.doWithLocalFields(targetClass, field -> {
if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
}
currElements.add(new WebServiceRefElement(field, field, null));
}
else if (ejbClass != null && field.isAnnotationPresent(ejbClass)) {
if (ejbClass != null && field.isAnnotationPresent(ejbClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static fields");
}
@ -389,17 +359,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
return;
}
if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
}
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
}
else if (ejbClass != null && bridgedMethod.isAnnotationPresent(ejbClass)) {
if (ejbClass != null && bridgedMethod.isAnnotationPresent(ejbClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static methods");
}
@ -649,91 +609,6 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
}
/**
* Class representing injection information about an annotated field
* or setter method, supporting the @WebServiceRef annotation.
*/
private class WebServiceRefElement extends LookupElement {
private final Class<?> elementType;
private final String wsdlLocation;
public WebServiceRefElement(Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) {
super(member, pd);
WebServiceRef resource = ae.getAnnotation(WebServiceRef.class);
String resourceName = resource.name();
Class<?> resourceType = resource.type();
this.isDefaultName = !StringUtils.hasLength(resourceName);
if (this.isDefaultName) {
resourceName = this.member.getName();
if (this.member instanceof Method && resourceName.startsWith("set") && resourceName.length() > 3) {
resourceName = Introspector.decapitalize(resourceName.substring(3));
}
}
if (Object.class != resourceType) {
checkResourceType(resourceType);
}
else {
// No resource type specified... check field/method.
resourceType = getResourceType();
}
this.name = resourceName;
this.elementType = resourceType;
if (Service.class.isAssignableFrom(resourceType)) {
this.lookupType = resourceType;
}
else {
this.lookupType = resource.value();
}
this.mappedName = resource.mappedName();
this.wsdlLocation = resource.wsdlLocation();
}
@Override
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
Service service;
try {
service = (Service) getResource(this, requestingBeanName);
}
catch (NoSuchBeanDefinitionException notFound) {
// Service to be created through generated class.
if (Service.class == this.lookupType) {
throw new IllegalStateException("No resource with name '" + this.name + "' found in context, " +
"and no specific JAX-WS Service subclass specified. The typical solution is to either specify " +
"a LocalJaxWsServiceFactoryBean with the given name or to specify the (generated) Service " +
"subclass as @WebServiceRef(...) value.");
}
if (StringUtils.hasLength(this.wsdlLocation)) {
try {
Constructor<?> ctor = this.lookupType.getConstructor(URL.class, QName.class);
WebServiceClient clientAnn = this.lookupType.getAnnotation(WebServiceClient.class);
if (clientAnn == null) {
throw new IllegalStateException("JAX-WS Service class [" + this.lookupType.getName() +
"] does not carry a WebServiceClient annotation");
}
service = (Service) BeanUtils.instantiateClass(ctor,
new URL(this.wsdlLocation), new QName(clientAnn.targetNamespace(), clientAnn.name()));
}
catch (NoSuchMethodException ex) {
throw new IllegalStateException("JAX-WS Service class [" + this.lookupType.getName() +
"] does not have a (URL, QName) constructor. Cannot apply specified WSDL location [" +
this.wsdlLocation + "].");
}
catch (MalformedURLException ex) {
throw new IllegalArgumentException(
"Specified WSDL location [" + this.wsdlLocation + "] isn't a valid URL");
}
}
else {
service = (Service) BeanUtils.instantiateClass(this.lookupType);
}
}
return service.getPort(this.elementType);
}
}
/**
* Class representing injection information about an annotated field
* or setter method, supporting the @EJB annotation.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@ -61,7 +61,7 @@ public class ClassPathBeanDefinitionScannerTests {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
int beanCount = scanner.scan(BASE_PACKAGE);
assertThat(beanCount).isEqualTo(12);
assertThat(beanCount).isGreaterThanOrEqualTo(12);
assertThat(context.containsBean("serviceInvocationCounter")).isTrue();
assertThat(context.containsBean("fooServiceImpl")).isTrue();
assertThat(context.containsBean("stubFooDao")).isTrue();
@ -110,7 +110,7 @@ public class ClassPathBeanDefinitionScannerTests {
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
int beanCount = scanner.scan(BASE_PACKAGE);
assertThat(beanCount).isEqualTo(12);
assertThat(beanCount).isGreaterThanOrEqualTo(12);
ClassPathBeanDefinitionScanner scanner2 = new ClassPathBeanDefinitionScanner(context) {
@Override
@ -138,7 +138,7 @@ public class ClassPathBeanDefinitionScannerTests {
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
int beanCount = scanner.scan(BASE_PACKAGE);
assertThat(beanCount).isEqualTo(12);
assertThat(beanCount).isGreaterThanOrEqualTo(12);
assertThat(context.containsBean("serviceInvocationCounter")).isTrue();
assertThat(context.containsBean("fooServiceImpl")).isTrue();
@ -157,7 +157,7 @@ public class ClassPathBeanDefinitionScannerTests {
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
int beanCount = scanner.scan(BASE_PACKAGE);
assertThat(beanCount).isEqualTo(12);
assertThat(beanCount).isGreaterThanOrEqualTo(12);
ClassPathBeanDefinitionScanner scanner2 = new ClassPathBeanDefinitionScanner(context) {
@Override
@ -182,7 +182,7 @@ public class ClassPathBeanDefinitionScannerTests {
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setIncludeAnnotationConfig(false);
int beanCount = scanner.scan(BASE_PACKAGE);
assertThat(beanCount).isEqualTo(7);
assertThat(beanCount).isGreaterThanOrEqualTo(7);
assertThat(context.containsBean("serviceInvocationCounter")).isTrue();
assertThat(context.containsBean("fooServiceImpl")).isTrue();
@ -222,7 +222,7 @@ public class ClassPathBeanDefinitionScannerTests {
scanner.setIncludeAnnotationConfig(false);
int scannedBeanCount = scanner.scan(BASE_PACKAGE);
assertThat(scannedBeanCount).isEqualTo(6);
assertThat(scannedBeanCount).isGreaterThanOrEqualTo(6);
assertThat(context.getBeanDefinitionCount()).isEqualTo((initialBeanCount + scannedBeanCount));
assertThat(context.containsBean("serviceInvocationCounter")).isTrue();
assertThat(context.containsBean("fooServiceImpl")).isTrue();
@ -242,7 +242,7 @@ public class ClassPathBeanDefinitionScannerTests {
scanner.setIncludeAnnotationConfig(false);
int scannedBeanCount = scanner.scan(BASE_PACKAGE);
assertThat(scannedBeanCount).isEqualTo(6);
assertThat(scannedBeanCount).isGreaterThanOrEqualTo(6);
assertThat(context.getBeanDefinitionCount()).isEqualTo((initialBeanCount + scannedBeanCount));
assertThat(context.containsBean("serviceInvocationCounter")).isTrue();
assertThat(context.containsBean("fooServiceImpl")).isTrue();
@ -281,7 +281,7 @@ public class ClassPathBeanDefinitionScannerTests {
scanner.addIncludeFilter(new AnnotationTypeFilter(CustomComponent.class));
int beanCount = scanner.scan(BASE_PACKAGE);
assertThat(beanCount).isEqualTo(6);
assertThat(beanCount).isGreaterThanOrEqualTo(6);
assertThat(context.containsBean("messageBean")).isTrue();
assertThat(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)).isTrue();
assertThat(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)).isTrue();
@ -296,7 +296,7 @@ public class ClassPathBeanDefinitionScannerTests {
scanner.addIncludeFilter(new AnnotationTypeFilter(CustomComponent.class));
int beanCount = scanner.scan(BASE_PACKAGE);
assertThat(beanCount).isEqualTo(6);
assertThat(beanCount).isGreaterThanOrEqualTo(6);
assertThat(context.containsBean("messageBean")).isTrue();
assertThat(context.containsBean("serviceInvocationCounter")).isFalse();
assertThat(context.containsBean("fooServiceImpl")).isFalse();
@ -316,7 +316,7 @@ public class ClassPathBeanDefinitionScannerTests {
scanner.addIncludeFilter(new AnnotationTypeFilter(CustomComponent.class));
int beanCount = scanner.scan(BASE_PACKAGE);
assertThat(beanCount).isEqualTo(13);
assertThat(beanCount).isGreaterThanOrEqualTo(13);
assertThat(context.containsBean("messageBean")).isTrue();
assertThat(context.containsBean("serviceInvocationCounter")).isTrue();
assertThat(context.containsBean("fooServiceImpl")).isTrue();
@ -336,7 +336,7 @@ public class ClassPathBeanDefinitionScannerTests {
scanner.addExcludeFilter(new AnnotationTypeFilter(Aspect.class));
int beanCount = scanner.scan(BASE_PACKAGE);
assertThat(beanCount).isEqualTo(11);
assertThat(beanCount).isGreaterThanOrEqualTo(11);
assertThat(context.containsBean("serviceInvocationCounter")).isFalse();
assertThat(context.containsBean("fooServiceImpl")).isTrue();
assertThat(context.containsBean("stubFooDao")).isTrue();
@ -354,7 +354,7 @@ public class ClassPathBeanDefinitionScannerTests {
scanner.addExcludeFilter(new AssignableTypeFilter(FooService.class));
int beanCount = scanner.scan(BASE_PACKAGE);
assertThat(beanCount).isEqualTo(11);
assertThat(beanCount).isGreaterThanOrEqualTo(11);
assertThat(context.containsBean("fooServiceImpl")).isFalse();
assertThat(context.containsBean("serviceInvocationCounter")).isTrue();
assertThat(context.containsBean("stubFooDao")).isTrue();
@ -374,7 +374,7 @@ public class ClassPathBeanDefinitionScannerTests {
scanner.addExcludeFilter(new AssignableTypeFilter(FooService.class));
int beanCount = scanner.scan(BASE_PACKAGE);
assertThat(beanCount).isEqualTo(6);
assertThat(beanCount).isGreaterThanOrEqualTo(6);
assertThat(context.containsBean("fooServiceImpl")).isFalse();
assertThat(context.containsBean("serviceInvocationCounter")).isTrue();
assertThat(context.containsBean("stubFooDao")).isTrue();
@ -392,7 +392,7 @@ public class ClassPathBeanDefinitionScannerTests {
scanner.addExcludeFilter(new AnnotationTypeFilter(Aspect.class));
int beanCount = scanner.scan(BASE_PACKAGE);
assertThat(beanCount).isEqualTo(10);
assertThat(beanCount).isGreaterThanOrEqualTo(10);
assertThat(context.containsBean("fooServiceImpl")).isFalse();
assertThat(context.containsBean("serviceInvocationCounter")).isFalse();
assertThat(context.containsBean("stubFooDao")).isTrue();
@ -411,7 +411,7 @@ public class ClassPathBeanDefinitionScannerTests {
scanner.setBeanNameGenerator(new TestBeanNameGenerator());
int beanCount = scanner.scan(BASE_PACKAGE);
assertThat(beanCount).isEqualTo(12);
assertThat(beanCount).isGreaterThanOrEqualTo(12);
assertThat(context.containsBean("fooServiceImpl")).isFalse();
assertThat(context.containsBean("fooService")).isTrue();
assertThat(context.containsBean("serviceInvocationCounter")).isTrue();
@ -431,7 +431,7 @@ public class ClassPathBeanDefinitionScannerTests {
GenericApplicationContext multiPackageContext = new GenericApplicationContext();
ClassPathBeanDefinitionScanner multiPackageScanner = new ClassPathBeanDefinitionScanner(multiPackageContext);
int singlePackageBeanCount = singlePackageScanner.scan(BASE_PACKAGE);
assertThat(singlePackageBeanCount).isEqualTo(12);
assertThat(singlePackageBeanCount).isGreaterThanOrEqualTo(12);
multiPackageScanner.scan(BASE_PACKAGE, "org.springframework.dao.annotation");
// assertTrue(multiPackageBeanCount > singlePackageBeanCount);
}
@ -442,7 +442,7 @@ public class ClassPathBeanDefinitionScannerTests {
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
int initialBeanCount = context.getBeanDefinitionCount();
int scannedBeanCount = scanner.scan(BASE_PACKAGE);
assertThat(scannedBeanCount).isEqualTo(12);
assertThat(scannedBeanCount).isGreaterThanOrEqualTo(12);
assertThat((context.getBeanDefinitionCount() - initialBeanCount)).isEqualTo(scannedBeanCount);
int addedBeanCount = scanner.scan("org.springframework.aop.aspectj.annotation");
assertThat(context.getBeanDefinitionCount()).isEqualTo((initialBeanCount + scannedBeanCount + addedBeanCount));
@ -455,7 +455,7 @@ public class ClassPathBeanDefinitionScannerTests {
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setBeanNameGenerator(new TestBeanNameGenerator());
int beanCount = scanner.scan(BASE_PACKAGE);
assertThat(beanCount).isEqualTo(12);
assertThat(beanCount).isGreaterThanOrEqualTo(12);
context.refresh();
FooServiceImpl fooService = context.getBean("fooService", FooServiceImpl.class);
@ -485,7 +485,7 @@ public class ClassPathBeanDefinitionScannerTests {
scanner.setIncludeAnnotationConfig(false);
scanner.setBeanNameGenerator(new TestBeanNameGenerator());
int beanCount = scanner.scan(BASE_PACKAGE);
assertThat(beanCount).isEqualTo(7);
assertThat(beanCount).isGreaterThanOrEqualTo(7);
context.refresh();
try {