Skip to content

Commit 774583d

Browse files
committed
Retain support for legacy PostConstruct/PreDestroy/Inject variants
Also removes JAX-WS support from CommonAnnotationBeanPostProcessor. Closes spring-projectsgh-27444 See spring-projectsgh-27422
1 parent 6976bf7 commit 774583d

File tree

7 files changed

+92
-183
lines changed

7 files changed

+92
-183
lines changed

build.gradle

-1
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,6 @@ configure(allprojects) { project ->
230230
dependency "jakarta.validation:jakarta.validation-api:3.0.0"
231231
dependency "jakarta.websocket:jakarta.websocket-api:2.0.0"
232232
dependency "jakarta.xml.bind:jakarta.xml.bind-api:3.0.1"
233-
dependency "jakarta.xml.ws:jakarta.xml.ws-api:3.0.1"
234233

235234
dependency "com.sun.activation:jakarta.activation:2.0.1"
236235
dependency "com.sun.mail:jakarta.mail:2.0.1"

spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java

+19-7
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,10 @@
7575
* by default, Spring's {@link Autowired @Autowired} and {@link Value @Value}
7676
* annotations.
7777
*
78-
* <p>Also supports JSR-330's {@link jakarta.inject.Inject @Inject} annotation,
78+
* <p>Also supports the common {@link jakarta.inject.Inject @Inject} annotation,
7979
* if available, as a direct alternative to Spring's own {@code @Autowired}.
80+
* Additionally, it retains support for the {@code javax.inject.Inject} variant
81+
* dating back to the original JSR-330 specification (as known from Java EE 6-8).
8082
*
8183
* <h3>Autowired Constructors</h3>
8284
* <p>Only one constructor of any given bean class may declare this annotation with
@@ -154,20 +156,30 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
154156
/**
155157
* Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's
156158
* standard {@link Autowired @Autowired} and {@link Value @Value} annotations.
157-
* <p>Also supports JSR-330's {@link jakarta.inject.Inject @Inject} annotation,
158-
* if available.
159+
* <p>Also supports the common {@link jakarta.inject.Inject @Inject} annotation,
160+
* if available, as well as the original {@code javax.inject.Inject} variant.
159161
*/
160162
@SuppressWarnings("unchecked")
161163
public AutowiredAnnotationBeanPostProcessor() {
162164
this.autowiredAnnotationTypes.add(Autowired.class);
163165
this.autowiredAnnotationTypes.add(Value.class);
166+
164167
try {
165168
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
166169
ClassUtils.forName("jakarta.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
167-
logger.trace("JSR-330 'jakarta.inject.Inject' annotation found and supported for autowiring");
170+
logger.trace("'jakarta.inject.Inject' annotation found and supported for autowiring");
171+
}
172+
catch (ClassNotFoundException ex) {
173+
// jakarta.inject API not available - simply skip.
174+
}
175+
176+
try {
177+
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
178+
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
179+
logger.trace("'javax.inject.Inject' annotation found and supported for autowiring");
168180
}
169181
catch (ClassNotFoundException ex) {
170-
// JSR-330 API not available - simply skip.
182+
// javax.inject API not available - simply skip.
171183
}
172184
}
173185

@@ -177,7 +189,7 @@ public AutowiredAnnotationBeanPostProcessor() {
177189
* setter methods, and arbitrary config methods.
178190
* <p>The default autowired annotation types are the Spring-provided
179191
* {@link Autowired @Autowired} and {@link Value @Value} annotations as well
180-
* as JSR-330's {@link jakarta.inject.Inject @Inject} annotation, if available.
192+
* as the common {@code @Inject} annotation, if available.
181193
* <p>This setter property exists so that developers can provide their own
182194
* (non-Spring-specific) annotation type to indicate that a member is supposed
183195
* to be autowired.
@@ -193,7 +205,7 @@ public void setAutowiredAnnotationType(Class<? extends Annotation> autowiredAnno
193205
* setter methods, and arbitrary config methods.
194206
* <p>The default autowired annotation types are the Spring-provided
195207
* {@link Autowired @Autowired} and {@link Value @Value} annotations as well
196-
* as JSR-330's {@link jakarta.inject.Inject @Inject} annotation, if available.
208+
* as the common {@code @Inject} annotation, if available.
197209
* <p>This setter property exists so that developers can provide their own
198210
* (non-Spring-specific) annotation types to indicate that a member is supposed
199211
* to be autowired.

spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -66,7 +66,7 @@
6666
* init method and destroy method, respectively.
6767
*
6868
* <p>Spring's {@link org.springframework.context.annotation.CommonAnnotationBeanPostProcessor}
69-
* supports the JSR-250 {@link jakarta.annotation.PostConstruct} and {@link jakarta.annotation.PreDestroy}
69+
* supports the {@link jakarta.annotation.PostConstruct} and {@link jakarta.annotation.PreDestroy}
7070
* annotations out of the box, as init annotation and destroy annotation, respectively.
7171
* Furthermore, it also supports the {@link jakarta.annotation.Resource} annotation
7272
* for annotation-driven injection of named beans.
@@ -117,7 +117,7 @@ public boolean hasDestroyMethods() {
117117
* methods to call after configuration of a bean.
118118
* <p>Any custom annotation can be used, since there are no required
119119
* annotation attributes. There is no default, although a typical choice
120-
* is the JSR-250 {@link jakarta.annotation.PostConstruct} annotation.
120+
* is the {@link jakarta.annotation.PostConstruct} annotation.
121121
*/
122122
public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) {
123123
this.initAnnotationType = initAnnotationType;
@@ -128,7 +128,7 @@ public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType
128128
* methods to call when the context is shutting down.
129129
* <p>Any custom annotation can be used, since there are no required
130130
* annotation attributes. There is no default, although a typical choice
131-
* is the JSR-250 {@link jakarta.annotation.PreDestroy} annotation.
131+
* is the {@link jakarta.annotation.PreDestroy} annotation.
132132
*/
133133
public void setDestroyAnnotationType(Class<? extends Annotation> destroyAnnotationType) {
134134
this.destroyAnnotationType = destroyAnnotationType;

spring-context/spring-context.gradle

+2-3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ dependencies {
1414
optional("jakarta.enterprise.concurrent:jakarta.enterprise.concurrent-api")
1515
optional("jakarta.inject:jakarta.inject-api")
1616
optional("jakarta.interceptor:jakarta.interceptor-api")
17-
optional("javax.money:money-api")
1817
optional("jakarta.validation:jakarta.validation-api")
19-
optional("jakarta.xml.ws:jakarta.xml.ws-api")
18+
optional("javax.money:money-api")
2019
optional("org.aspectj:aspectjweaver")
2120
optional("org.codehaus.groovy:groovy")
2221
optional("org.apache-extras.beanshell:bsh")
@@ -32,8 +31,8 @@ dependencies {
3231
testImplementation("org.codehaus.groovy:groovy-test")
3332
testImplementation("org.codehaus.groovy:groovy-xml")
3433
testImplementation("org.apache.commons:commons-pool2")
35-
testImplementation("jakarta.inject:jakarta.inject-tck")
3634
testImplementation("org.awaitility:awaitility")
35+
testImplementation("jakarta.inject:jakarta.inject-tck")
3736
testRuntimeOnly("jakarta.xml.bind:jakarta.xml.bind-api")
3837
testRuntimeOnly("org.glassfish:jakarta.el")
3938
// Substitute for javax.management:jmxremote_optional:1.0.1_04 (not available on Maven Central)

spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java

+36-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
2323

2424
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
2525
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
26+
import org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor;
2627
import org.springframework.beans.factory.config.BeanDefinition;
2728
import org.springframework.beans.factory.config.BeanDefinitionHolder;
2829
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@@ -91,11 +92,17 @@ public abstract class AnnotationConfigUtils {
9192
"org.springframework.context.annotation.internalRequiredAnnotationProcessor";
9293

9394
/**
94-
* The bean name of the internally managed JSR-250 annotation processor.
95+
* The bean name of the internally managed common annotation processor.
9596
*/
9697
public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME =
9798
"org.springframework.context.annotation.internalCommonAnnotationProcessor";
9899

100+
/**
101+
* The bean name of the internally managed JSR-250 annotation processor.
102+
*/
103+
private static final String JSR250_ANNOTATION_PROCESSOR_BEAN_NAME =
104+
"org.springframework.context.annotation.internalJsr250AnnotationProcessor";
105+
99106
/**
100107
* The bean name of the internally managed JPA annotation processor.
101108
*/
@@ -117,16 +124,18 @@ public abstract class AnnotationConfigUtils {
117124
public static final String EVENT_LISTENER_FACTORY_BEAN_NAME =
118125
"org.springframework.context.event.internalEventListenerFactory";
119126

120-
private static final boolean jsr250Present;
121127

122-
private static final boolean jpaPresent;
128+
private static final ClassLoader classLoader = AnnotationConfigUtils.class.getClassLoader();
123129

124-
static {
125-
ClassLoader classLoader = AnnotationConfigUtils.class.getClassLoader();
126-
jsr250Present = ClassUtils.isPresent("jakarta.annotation.Resource", classLoader);
127-
jpaPresent = ClassUtils.isPresent("jakarta.persistence.EntityManagerFactory", classLoader) &&
128-
ClassUtils.isPresent(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, classLoader);
129-
}
130+
private static final boolean jakartaAnnotationsPresent =
131+
ClassUtils.isPresent("jakarta.annotation.PostConstruct", classLoader);
132+
133+
private static final boolean jsr250Present =
134+
ClassUtils.isPresent("javax.annotation.PostConstruct", classLoader);
135+
136+
private static final boolean jpaPresent =
137+
ClassUtils.isPresent("jakarta.persistence.EntityManagerFactory", classLoader) &&
138+
ClassUtils.isPresent(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, classLoader);
130139

131140

132141
/**
@@ -172,13 +181,28 @@ public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
172181
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
173182
}
174183

175-
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
176-
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
184+
// Check for Jakarta Annotations support, and if present add the CommonAnnotationBeanPostProcessor.
185+
if (jakartaAnnotationsPresent && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
177186
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
178187
def.setSource(source);
179188
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
180189
}
181190

191+
// Check for JSR-250 support, and if present add an InitDestroyAnnotationBeanPostProcessor
192+
// for the javax variant of PostConstruct/PreDestroy.
193+
if (jsr250Present && !registry.containsBeanDefinition(JSR250_ANNOTATION_PROCESSOR_BEAN_NAME)) {
194+
try {
195+
RootBeanDefinition def = new RootBeanDefinition(InitDestroyAnnotationBeanPostProcessor.class);
196+
def.getPropertyValues().add("initAnnotationType", classLoader.loadClass("javax.annotation.PostConstruct"));
197+
def.getPropertyValues().add("destroyAnnotationType", classLoader.loadClass("javax.annotation.PreDestroy"));
198+
def.setSource(source);
199+
beanDefs.add(registerPostProcessor(registry, def, JSR250_ANNOTATION_PROCESSOR_BEAN_NAME));
200+
}
201+
catch (ClassNotFoundException ex) {
202+
// Failed to load javax variants of the annotation types -> ignore.
203+
}
204+
}
205+
182206
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
183207
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
184208
RootBeanDefinition def = new RootBeanDefinition();

0 commit comments

Comments
 (0)