Skip to content

Commit 81cb740

Browse files
committed
New postProcessProperties variant on InstantiationAwareBeanPostProcessor
Allows for skipping the now-deprecated postProcessPropertyValues callback with its expensive PropertyDescriptor retrieval requirement. RequiredAnnotationBeanPostProcessor (which is dependent on postProcessPropertyValues) and the @required annotation itself are also deprecated now: in favor of constructor injection (or afterPropertiesSet). Issue: SPR-16918
1 parent 7946935 commit 81cb740

File tree

19 files changed

+178
-123
lines changed

19 files changed

+178
-123
lines changed

spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAutoProxyCreator.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package org.springframework.aop.framework.autoproxy;
1818

19-
import java.beans.PropertyDescriptor;
2019
import java.lang.reflect.Constructor;
2120
import java.util.ArrayList;
2221
import java.util.Arrays;
@@ -230,12 +229,12 @@ public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
230229

231230
@Override
232231
@Nullable
233-
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
232+
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) {
234233
return null;
235234
}
236235

237236
@Override
238-
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
237+
public Object getEarlyBeanReference(Object bean, String beanName) {
239238
Object cacheKey = getCacheKey(bean.getClass(), beanName);
240239
if (!this.earlyProxyReferences.contains(cacheKey)) {
241240
this.earlyProxyReferences.add(cacheKey);
@@ -244,7 +243,7 @@ public Object getEarlyBeanReference(Object bean, String beanName) throws BeansEx
244243
}
245244

246245
@Override
247-
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
246+
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
248247
Object cacheKey = getCacheKey(beanClass, beanName);
249248

250249
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
@@ -280,9 +279,7 @@ public boolean postProcessAfterInstantiation(Object bean, String beanName) {
280279
}
281280

282281
@Override
283-
public PropertyValues postProcessPropertyValues(
284-
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
285-
282+
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
286283
return pvs;
287284
}
288285

@@ -297,7 +294,7 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) {
297294
* @see #getAdvicesAndAdvisorsForBean
298295
*/
299296
@Override
300-
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
297+
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
301298
if (bean != null) {
302299
Object cacheKey = getCacheKey(bean.getClass(), beanName);
303300
if (!this.earlyProxyReferences.contains(cacheKey)) {

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,9 +365,7 @@ else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
365365
}
366366

367367
@Override
368-
public PropertyValues postProcessPropertyValues(
369-
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
370-
368+
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
371369
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
372370
try {
373371
metadata.inject(bean, beanName, pvs);
@@ -381,6 +379,14 @@ public PropertyValues postProcessPropertyValues(
381379
return pvs;
382380
}
383381

382+
@Deprecated
383+
@Override
384+
public PropertyValues postProcessPropertyValues(
385+
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
386+
387+
return postProcessProperties(pvs, bean, beanName);
388+
}
389+
384390
/**
385391
* 'Native' processing method for direct calls with an arbitrary target instance,
386392
* resolving all of its fields and methods which are annotated with {@code @Autowired}.

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2018 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.
@@ -31,7 +31,10 @@
3131
* @author Rob Harrop
3232
* @since 2.0
3333
* @see RequiredAnnotationBeanPostProcessor
34+
* @deprecated as of 5.1, in favor of using constructor injection for required settings
35+
* (or a custom {@link org.springframework.beans.factory.InitializingBean} implementation)
3436
*/
37+
@Deprecated
3538
@Retention(RetentionPolicy.RUNTIME)
3639
@Target(ElementType.METHOD)
3740
public @interface Required {

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import java.util.Set;
2626
import java.util.concurrent.ConcurrentHashMap;
2727

28-
import org.springframework.beans.BeansException;
2928
import org.springframework.beans.PropertyValues;
3029
import org.springframework.beans.factory.BeanFactory;
3130
import org.springframework.beans.factory.BeanFactoryAware;
@@ -72,7 +71,10 @@
7271
* @since 2.0
7372
* @see #setRequiredAnnotationType
7473
* @see Required
74+
* @deprecated as of 5.1, in favor of using constructor injection for required settings
75+
* (or a custom {@link org.springframework.beans.factory.InitializingBean} implementation)
7576
*/
77+
@Deprecated
7678
public class RequiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
7779
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
7880

@@ -142,7 +144,7 @@ public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, C
142144

143145
@Override
144146
public PropertyValues postProcessPropertyValues(
145-
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
147+
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
146148

147149
if (!this.validatedBeanNames.contains(beanName)) {
148150
if (!shouldSkip(this.beanFactory, beanName)) {

spring-beans/src/main/java/org/springframework/beans/factory/config/InstantiationAwareBeanPostProcessor.java

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 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.
@@ -55,7 +55,7 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
5555
* {@link #postProcessAfterInitialization} callback from the configured
5656
* {@link BeanPostProcessor BeanPostProcessors}.
5757
* <p>This callback will only be applied to bean definitions with a bean class.
58-
* In particular, it will not be applied to beans with a "factory-method".
58+
* In particular, it will not be applied to beans with a factory method.
5959
* <p>Post-processors may implement the extended
6060
* {@link SmartInstantiationAwareBeanPostProcessor} interface in order
6161
* to predict the type of the bean object that they are going to return here.
@@ -65,8 +65,8 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
6565
* @return the bean object to expose instead of a default instance of the target bean,
6666
* or {@code null} to proceed with default instantiation
6767
* @throws org.springframework.beans.BeansException in case of errors
68+
* @see #postProcessAfterInstantiation
6869
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#hasBeanClass
69-
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#getFactoryMethodName
7070
*/
7171
@Nullable
7272
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
@@ -86,11 +86,37 @@ default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanNam
8686
* Returning {@code false} will also prevent any subsequent InstantiationAwareBeanPostProcessor
8787
* instances being invoked on this bean instance.
8888
* @throws org.springframework.beans.BeansException in case of errors
89+
* @see #postProcessBeforeInstantiation
8990
*/
9091
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
9192
return true;
9293
}
9394

95+
/**
96+
* Post-process the given property values before the factory applies them
97+
* to the given bean, without any need for property descriptors.
98+
* <p>Implementations should return {@code null} (the default) if they provide a custom
99+
* {@link #postProcessPropertyValues} implementation, and {@code pvs} otherwise.
100+
* In a future version of this interface (with {@link #postProcessPropertyValues} removed),
101+
* the default implementation will return the given {@code pvs} as-is directly.
102+
* @param pvs the property values that the factory is about to apply (never {@code null})
103+
* @param bean the bean instance created, but whose properties have not yet been set
104+
* @param beanName the name of the bean
105+
* @return the actual property values to apply to the given bean (can be the passed-in
106+
* PropertyValues instance), or {@code null} which proceeds with the existing properties
107+
* but specifically continues with a call to {@link #postProcessPropertyValues}
108+
* (requiring initialized {@code PropertyDescriptor}s for the current bean class)
109+
* @throws org.springframework.beans.BeansException in case of errors
110+
* @since 5.1
111+
* @see #postProcessPropertyValues
112+
*/
113+
@Nullable
114+
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
115+
throws BeansException {
116+
117+
return null;
118+
}
119+
94120
/**
95121
* Post-process the given property values before the factory applies them
96122
* to the given bean. Allows for checking whether all dependencies have been
@@ -104,12 +130,14 @@ default boolean postProcessAfterInstantiation(Object bean, String beanName) thro
104130
* dependency types - which the factory handles specifically - already filtered out)
105131
* @param bean the bean instance created, but whose properties have not yet been set
106132
* @param beanName the name of the bean
107-
* @return the actual property values to apply to the given bean
108-
* (can be the passed-in PropertyValues instance), or {@code null}
109-
* to skip property population
133+
* @return the actual property values to apply to the given bean (can be the passed-in
134+
* PropertyValues instance), or {@code null} to skip property population
110135
* @throws org.springframework.beans.BeansException in case of errors
136+
* @see #postProcessProperties
111137
* @see org.springframework.beans.MutablePropertyValues
138+
* @deprecated as of 5.1, in favor of {@link #postProcessProperties(PropertyValues, Object, String)}
112139
*/
140+
@Deprecated
113141
@Nullable
114142
default PropertyValues postProcessPropertyValues(
115143
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

spring-beans/src/main/java/org/springframework/beans/factory/config/InstantiationAwareBeanPostProcessorAdapter.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2018 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.
@@ -42,7 +42,7 @@ public abstract class InstantiationAwareBeanPostProcessorAdapter implements Smar
4242

4343
@Override
4444
@Nullable
45-
public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
45+
public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
4646
return null;
4747
}
4848

@@ -68,6 +68,14 @@ public boolean postProcessAfterInstantiation(Object bean, String beanName) throw
6868
return true;
6969
}
7070

71+
@Override
72+
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
73+
throws BeansException {
74+
75+
return null;
76+
}
77+
78+
@Deprecated
7179
@Override
7280
public PropertyValues postProcessPropertyValues(
7381
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,6 +1292,7 @@ protected BeanWrapper autowireConstructor(
12921292
* @param mbd the bean definition for the bean
12931293
* @param bw the BeanWrapper with bean instance
12941294
*/
1295+
@SuppressWarnings("deprecation") // for postProcessPropertyValues
12951296
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
12961297
if (bw == null) {
12971298
if (mbd.hasPropertyValues()) {
@@ -1347,25 +1348,33 @@ protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable B
13471348
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
13481349
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
13491350

1350-
if (hasInstAwareBpps || needsDepCheck) {
1351+
PropertyDescriptor[] filteredPds = null;
1352+
if (hasInstAwareBpps) {
13511353
if (pvs == null) {
13521354
pvs = mbd.getPropertyValues();
13531355
}
1354-
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
1355-
if (hasInstAwareBpps) {
1356-
for (BeanPostProcessor bp : getBeanPostProcessors()) {
1357-
if (bp instanceof InstantiationAwareBeanPostProcessor) {
1358-
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
1359-
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
1360-
if (pvs == null) {
1356+
for (BeanPostProcessor bp : getBeanPostProcessors()) {
1357+
if (bp instanceof InstantiationAwareBeanPostProcessor) {
1358+
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
1359+
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
1360+
if (pvsToUse == null) {
1361+
if (filteredPds == null) {
1362+
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
1363+
}
1364+
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
1365+
if (pvsToUse == null) {
13611366
return;
13621367
}
13631368
}
1369+
pvs = pvsToUse;
13641370
}
13651371
}
1366-
if (needsDepCheck) {
1367-
checkDependencies(beanName, mbd, filteredPds, pvs);
1372+
}
1373+
if (needsDepCheck) {
1374+
if (filteredPds == null) {
1375+
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
13681376
}
1377+
checkDependencies(beanName, mbd, filteredPds, pvs);
13691378
}
13701379

13711380
if (pvs != null) {
@@ -1543,12 +1552,12 @@ protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
15431552
* @see #isExcludedFromDependencyCheck(java.beans.PropertyDescriptor)
15441553
*/
15451554
protected void checkDependencies(
1546-
String beanName, AbstractBeanDefinition mbd, PropertyDescriptor[] pds, PropertyValues pvs)
1555+
String beanName, AbstractBeanDefinition mbd, PropertyDescriptor[] pds, @Nullable PropertyValues pvs)
15471556
throws UnsatisfiedDependencyException {
15481557

15491558
int dependencyCheck = mbd.getDependencyCheck();
15501559
for (PropertyDescriptor pd : pds) {
1551-
if (pd.getWriteMethod() != null && !pvs.contains(pd.getName())) {
1560+
if (pd.getWriteMethod() != null && (pvs == null || !pvs.contains(pd.getName()))) {
15521561
boolean isSimple = BeanUtils.isSimpleProperty(pd.getPropertyType());
15531562
boolean unsatisfied = (dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_ALL) ||
15541563
(isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_SIMPLE) ||

spring-beans/src/test/java/org/springframework/beans/factory/annotation/RequiredAnnotationBeanPostProcessorTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2018 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.
@@ -39,6 +39,7 @@
3939
* @author Chris Beams
4040
* @since 2.0
4141
*/
42+
@Deprecated
4243
public class RequiredAnnotationBeanPostProcessorTests {
4344

4445
@Test

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

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
2525
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
26-
import org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor;
2726
import org.springframework.beans.factory.config.BeanDefinition;
2827
import org.springframework.beans.factory.config.BeanDefinitionHolder;
2928
import org.springframework.beans.factory.support.AbstractBeanDefinition;
@@ -54,10 +53,9 @@
5453
* @author Stephane Nicoll
5554
* @since 2.5
5655
* @see ContextAnnotationAutowireCandidateResolver
57-
* @see CommonAnnotationBeanPostProcessor
5856
* @see ConfigurationClassPostProcessor
57+
* @see CommonAnnotationBeanPostProcessor
5958
* @see org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
60-
* @see org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
6159
* @see org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor
6260
*/
6361
public final class AnnotationConfigUtils {
@@ -87,7 +85,9 @@ public final class AnnotationConfigUtils {
8785

8886
/**
8987
* The bean name of the internally managed Required annotation processor.
88+
* @deprecated as of 5.1, since no Required processor is registered by default anymore
9089
*/
90+
@Deprecated
9191
public static final String REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
9292
"org.springframework.context.annotation.internalRequiredAnnotationProcessor";
9393

@@ -103,7 +103,6 @@ public final class AnnotationConfigUtils {
103103
public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME =
104104
"org.springframework.context.annotation.internalPersistenceAnnotationProcessor";
105105

106-
107106
private static final String PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME =
108107
"org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor";
109108

@@ -174,12 +173,6 @@ public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
174173
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
175174
}
176175

177-
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
178-
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
179-
def.setSource(source);
180-
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
181-
}
182-
183176
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
184177
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
185178
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);

0 commit comments

Comments
 (0)