diff --git a/build.gradle b/build.gradle index 42f5225e9b..ac8e486325 100644 --- a/build.gradle +++ b/build.gradle @@ -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" diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java index fdbf935391..d5c753e729 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java @@ -75,8 +75,10 @@ import org.springframework.util.StringUtils; * by default, Spring's {@link Autowired @Autowired} and {@link Value @Value} * annotations. * - *
Also supports JSR-330's {@link jakarta.inject.Inject @Inject} annotation, + *
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). * *
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. - *
Also supports JSR-330's {@link jakarta.inject.Inject @Inject} annotation, - * if available. + *
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. *
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. *
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. *
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. *
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. diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java index 6316848a5a..2f1bd7763b 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java @@ -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. * *
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. *
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. *
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; diff --git a/spring-context/spring-context.gradle b/spring-context/spring-context.gradle index 9e4cf72ca9..f7bb843fcc 100644 --- a/spring-context/spring-context.gradle +++ b/spring-context/spring-context.gradle @@ -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) diff --git a/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java b/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java index 9c253124ee..20ed51eff6 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java @@ -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(); diff --git a/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java b/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java index 75b7d08afe..3bd70bc53c 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java @@ -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). * *
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. * - *
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 + *
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 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