Skip to content

Commit d257833

Browse files
committed
Merge branch '5.1.x'
2 parents bb05ee7 + b8e663c commit d257833

File tree

10 files changed

+196
-82
lines changed

10 files changed

+196
-82
lines changed

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

+4-6
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-2019 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.
@@ -133,7 +133,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
133133

134134
private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
135135

136-
private final Set<Object> earlyProxyReferences = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
136+
private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);
137137

138138
private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);
139139

@@ -236,9 +236,7 @@ public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, Strin
236236
@Override
237237
public Object getEarlyBeanReference(Object bean, String beanName) {
238238
Object cacheKey = getCacheKey(bean.getClass(), beanName);
239-
if (!this.earlyProxyReferences.contains(cacheKey)) {
240-
this.earlyProxyReferences.add(cacheKey);
241-
}
239+
this.earlyProxyReferences.put(cacheKey, bean);
242240
return wrapIfNecessary(bean, beanName, cacheKey);
243241
}
244242

@@ -297,7 +295,7 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) {
297295
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
298296
if (bean != null) {
299297
Object cacheKey = getCacheKey(bean.getClass(), beanName);
300-
if (!this.earlyProxyReferences.contains(cacheKey)) {
298+
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
301299
return wrapIfNecessary(bean, beanName, cacheKey);
302300
}
303301
}

spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java

+2-3
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-2019 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.
@@ -133,8 +133,7 @@ public interface BeanFactory {
133133
* Will ask the parent factory if the bean cannot be found in this factory instance.
134134
* @param name the name of the bean to retrieve
135135
* @return an instance of the bean
136-
* @throws NoSuchBeanDefinitionException if there is no bean definition
137-
* with the specified name
136+
* @throws NoSuchBeanDefinitionException if there is no bean with the specified name
138137
* @throws BeansException if the bean could not be obtained
139138
*/
140139
Object getBean(String name) throws BeansException;

spring-beans/src/main/java/org/springframework/beans/factory/InjectionPoint.java

+3-1
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-2019 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.
@@ -29,6 +29,8 @@
2929
/**
3030
* A simple descriptor for an injection point, pointing to a method/constructor
3131
* parameter or a field. Exposed by {@link UnsatisfiedDependencyException}.
32+
* Also available as an argument for factory methods, reacting to the
33+
* requesting injection point for building a customized bean instance.
3234
*
3335
* @author Juergen Hoeller
3436
* @since 4.3

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

+18-3
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-2019 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.
@@ -337,8 +337,7 @@ Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String be
337337
* including its bean name.
338338
* <p>This is effectively a variant of {@link #getBean(Class)} which preserves the
339339
* bean name of the matching instance.
340-
* @param requiredType type the bean must match; can be an interface or superclass.
341-
* {@code null} is disallowed.
340+
* @param requiredType type the bean must match; can be an interface or superclass
342341
* @return the bean name plus bean instance
343342
* @throws NoSuchBeanDefinitionException if no matching bean was found
344343
* @throws NoUniqueBeanDefinitionException if more than one matching bean was found
@@ -348,6 +347,22 @@ Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String be
348347
*/
349348
<T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;
350349

350+
/**
351+
* Resolve a bean instance for the given bean name, providing a dependency descriptor
352+
* for exposure to target factory methods.
353+
* <p>This is effectively a variant of {@link #getBean(String, Class)} which supports
354+
* factory methods with an {@link org.springframework.beans.factory.InjectionPoint}
355+
* argument.
356+
* @param name the name of the bean to look up
357+
* @param descriptor the dependency descriptor for the requesting injection point
358+
* @return the corresponding bean instance
359+
* @throws NoSuchBeanDefinitionException if there is no bean with the specified name
360+
* @throws BeansException if the bean could not be created
361+
* @since 5.1.5
362+
* @see #getBean(String, Class)
363+
*/
364+
Object resolveBeanByName(String name, DependencyDescriptor descriptor) throws BeansException;
365+
351366
/**
352367
* Resolve the specified dependency against the beans defined in this factory.
353368
* @param descriptor the descriptor for the dependency (field/method/constructor)

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

+24-7
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-2019 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.
@@ -58,6 +58,7 @@
5858
import org.springframework.beans.factory.BeanNameAware;
5959
import org.springframework.beans.factory.FactoryBean;
6060
import org.springframework.beans.factory.InitializingBean;
61+
import org.springframework.beans.factory.InjectionPoint;
6162
import org.springframework.beans.factory.UnsatisfiedDependencyException;
6263
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
6364
import org.springframework.beans.factory.config.BeanDefinition;
@@ -337,12 +338,6 @@ public Object configureBean(Object existingBean, String beanName) throws BeansEx
337338
return initializeBean(beanName, existingBean, bd);
338339
}
339340

340-
@Override
341-
@Nullable
342-
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException {
343-
return resolveDependency(descriptor, requestingBeanName, null, null);
344-
}
345-
346341

347342
//-------------------------------------------------------------------------
348343
// Specialized methods for fine-grained control over the bean lifecycle
@@ -446,6 +441,28 @@ public void destroyBean(Object existingBean) {
446441
}
447442

448443

444+
//-------------------------------------------------------------------------
445+
// Delegate methods for resolving injection points
446+
//-------------------------------------------------------------------------
447+
448+
@Override
449+
public Object resolveBeanByName(String name, DependencyDescriptor descriptor) {
450+
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
451+
try {
452+
return getBean(name, descriptor.getDependencyType());
453+
}
454+
finally {
455+
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
456+
}
457+
}
458+
459+
@Override
460+
@Nullable
461+
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException {
462+
return resolveDependency(descriptor, requestingBeanName, null, null);
463+
}
464+
465+
449466
//---------------------------------------------------------------------
450467
// Implementation of relevant AbstractBeanFactory template methods
451468
//---------------------------------------------------------------------

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

+14-8
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-2019 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.
@@ -512,13 +512,19 @@ protected Object autowireResource(BeanFactory factory, LookupElement element, @N
512512
Set<String> autowiredBeanNames;
513513
String name = element.name;
514514

515-
if (this.fallbackToDefaultTypeMatch && element.isDefaultName &&
516-
factory instanceof AutowireCapableBeanFactory && !factory.containsBean(name)) {
517-
autowiredBeanNames = new LinkedHashSet<>();
518-
resource = ((AutowireCapableBeanFactory) factory).resolveDependency(
519-
element.getDependencyDescriptor(), requestingBeanName, autowiredBeanNames, null);
520-
if (resource == null) {
521-
throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
515+
if (factory instanceof AutowireCapableBeanFactory) {
516+
AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
517+
DependencyDescriptor descriptor = element.getDependencyDescriptor();
518+
if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {
519+
autowiredBeanNames = new LinkedHashSet<>();
520+
resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
521+
if (resource == null) {
522+
throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
523+
}
524+
}
525+
else {
526+
resource = beanFactory.resolveBeanByName(name, descriptor);
527+
autowiredBeanNames = Collections.singleton(name);
522528
}
523529
}
524530
else {

spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java

+28-6
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-2019 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.
@@ -212,7 +212,11 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
212212
/** Statically specified listeners. */
213213
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
214214

215-
/** ApplicationEvents published early. */
215+
/** Local listeners registered before refresh. */
216+
@Nullable
217+
private Set<ApplicationListener<?>> earlyApplicationListeners;
218+
219+
/** ApplicationEvents published before the multicaster setup. */
216220
@Nullable
217221
private Set<ApplicationEvent> earlyApplicationEvents;
218222

@@ -483,7 +487,6 @@ public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor)
483487
this.beanFactoryPostProcessors.add(postProcessor);
484488
}
485489

486-
487490
/**
488491
* Return the list of BeanFactoryPostProcessors that will get applied
489492
* to the internal BeanFactory.
@@ -578,6 +581,7 @@ public void refresh() throws BeansException, IllegalStateException {
578581
* active flag as well as performing any initialization of property sources.
579582
*/
580583
protected void prepareRefresh() {
584+
// Switch to active.
581585
this.startupDate = System.currentTimeMillis();
582586
this.closed.set(false);
583587
this.active.set(true);
@@ -591,13 +595,23 @@ protected void prepareRefresh() {
591595
}
592596
}
593597

594-
// Initialize any placeholder property sources in the context environment
598+
// Initialize any placeholder property sources in the context environment.
595599
initPropertySources();
596600

597-
// Validate that all properties marked as required are resolvable
601+
// Validate that all properties marked as required are resolvable:
598602
// see ConfigurablePropertyResolver#setRequiredProperties
599603
getEnvironment().validateRequiredProperties();
600604

605+
// Store pre-refresh ApplicationListeners...
606+
if (this.earlyApplicationListeners == null) {
607+
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
608+
}
609+
else {
610+
// Reset local application listeners to pre-refresh state.
611+
this.applicationListeners.clear();
612+
this.applicationListeners.addAll(this.earlyApplicationListeners);
613+
}
614+
601615
// Allow for the collection of early ApplicationEvents,
602616
// to be published once the multicaster is available...
603617
this.earlyApplicationEvents = new LinkedHashSet<>();
@@ -982,6 +996,7 @@ public void close() {
982996
* @see #registerShutdownHook()
983997
*/
984998
protected void doClose() {
999+
// Check whether an actual close attempt is necessary...
9851000
if (this.active.get() && this.closed.compareAndSet(false, true)) {
9861001
if (logger.isDebugEnabled()) {
9871002
logger.debug("Closing " + this);
@@ -1016,6 +1031,13 @@ protected void doClose() {
10161031
// Let subclasses do some final clean-up if they wish...
10171032
onClose();
10181033

1034+
// Reset local application listeners to pre-refresh state.
1035+
if (this.earlyApplicationListeners != null) {
1036+
this.applicationListeners.clear();
1037+
this.applicationListeners.addAll(this.earlyApplicationListeners);
1038+
}
1039+
1040+
// Switch to inactive.
10191041
this.active.set(false);
10201042
}
10211043
}
@@ -1302,7 +1324,7 @@ private MessageSource getMessageSource() throws IllegalStateException {
13021324
@Nullable
13031325
protected MessageSource getInternalParentMessageSource() {
13041326
return (getParent() instanceof AbstractApplicationContext ?
1305-
((AbstractApplicationContext) getParent()).messageSource : getParent());
1327+
((AbstractApplicationContext) getParent()).messageSource : getParent());
13061328
}
13071329

13081330

spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassProcessingTests.java

+33-1
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-2019 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.
@@ -21,6 +21,7 @@
2121
import java.util.List;
2222
import java.util.Set;
2323
import java.util.function.Supplier;
24+
import javax.annotation.Resource;
2425
import javax.inject.Provider;
2526

2627
import org.junit.Rule;
@@ -228,6 +229,22 @@ public void configurationWithAdaptivePrototypes() {
228229
ctx.close();
229230
}
230231

232+
@Test
233+
public void configurationWithAdaptiveResourcePrototypes() {
234+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
235+
ctx.register(ConfigWithPrototypeBean.class, AdaptiveResourceInjectionPoints.class);
236+
ctx.refresh();
237+
238+
AdaptiveResourceInjectionPoints adaptive = ctx.getBean(AdaptiveResourceInjectionPoints.class);
239+
assertEquals("adaptiveInjectionPoint1", adaptive.adaptiveInjectionPoint1.getName());
240+
assertEquals("setAdaptiveInjectionPoint2", adaptive.adaptiveInjectionPoint2.getName());
241+
242+
adaptive = ctx.getBean(AdaptiveResourceInjectionPoints.class);
243+
assertEquals("adaptiveInjectionPoint1", adaptive.adaptiveInjectionPoint1.getName());
244+
assertEquals("setAdaptiveInjectionPoint2", adaptive.adaptiveInjectionPoint2.getName());
245+
ctx.close();
246+
}
247+
231248
@Test
232249
public void configurationWithPostProcessor() {
233250
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
@@ -444,6 +461,21 @@ public void setAdaptiveInjectionPoint2(TestBean adaptiveInjectionPoint2) {
444461
}
445462

446463

464+
@Scope("prototype")
465+
static class AdaptiveResourceInjectionPoints {
466+
467+
@Resource(name = "adaptive1")
468+
public TestBean adaptiveInjectionPoint1;
469+
470+
public TestBean adaptiveInjectionPoint2;
471+
472+
@Resource(name = "adaptive2")
473+
public void setAdaptiveInjectionPoint2(TestBean adaptiveInjectionPoint2) {
474+
this.adaptiveInjectionPoint2 = adaptiveInjectionPoint2;
475+
}
476+
}
477+
478+
447479
static class ConfigWithPostProcessor extends ConfigWithPrototypeBean {
448480

449481
@Value("${myProp}")

spring-test/src/main/java/org/springframework/test/web/servlet/setup/StubWebApplicationContext.java

+6-1
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-2019 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.
@@ -411,6 +411,11 @@ public <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws Bea
411411
throw new UnsupportedOperationException("Dependency resolution not supported");
412412
}
413413

414+
@Override
415+
public Object resolveBeanByName(String name, DependencyDescriptor descriptor) throws BeansException {
416+
throw new UnsupportedOperationException("Dependency resolution not supported");
417+
}
418+
414419
@Override
415420
@Nullable
416421
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) {

0 commit comments

Comments
 (0)