Skip to content

Commit 292f581

Browse files
committed
Populate dependencies metadata for resolved target behind lazy dependency proxy
Closes gh-25562
1 parent 686f5d4 commit 292f581

File tree

2 files changed

+27
-8
lines changed

2 files changed

+27
-8
lines changed

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

Lines changed: 18 additions & 5 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-2020 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.
@@ -20,12 +20,14 @@
2020
import java.lang.reflect.Method;
2121
import java.util.Collection;
2222
import java.util.Collections;
23+
import java.util.LinkedHashSet;
2324
import java.util.List;
2425
import java.util.Map;
2526
import java.util.Set;
2627

2728
import org.springframework.aop.TargetSource;
2829
import org.springframework.aop.framework.ProxyFactory;
30+
import org.springframework.beans.factory.BeanFactory;
2931
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
3032
import org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver;
3133
import org.springframework.beans.factory.config.DependencyDescriptor;
@@ -73,9 +75,11 @@ protected boolean isLazy(DependencyDescriptor descriptor) {
7375
}
7476

7577
protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) {
76-
Assert.state(getBeanFactory() instanceof DefaultListableBeanFactory,
78+
BeanFactory beanFactory = getBeanFactory();
79+
Assert.state(beanFactory instanceof DefaultListableBeanFactory,
7780
"BeanFactory needs to be a DefaultListableBeanFactory");
78-
final DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) getBeanFactory();
81+
final DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory;
82+
7983
TargetSource ts = new TargetSource() {
8084
@Override
8185
public Class<?> getTargetClass() {
@@ -87,7 +91,8 @@ public boolean isStatic() {
8791
}
8892
@Override
8993
public Object getTarget() {
90-
Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null);
94+
Set<String> autowiredBeanNames = (beanName != null ? new LinkedHashSet<>(1) : null);
95+
Object target = dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, null);
9196
if (target == null) {
9297
Class<?> type = getTargetClass();
9398
if (Map.class == type) {
@@ -102,19 +107,27 @@ else if (Set.class == type || Collection.class == type) {
102107
throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),
103108
"Optional dependency not present for lazy injection point");
104109
}
110+
if (autowiredBeanNames != null) {
111+
for (String autowiredBeanName : autowiredBeanNames) {
112+
if (dlbf.containsBean(autowiredBeanName)) {
113+
dlbf.registerDependentBean(autowiredBeanName, beanName);
114+
}
115+
}
116+
}
105117
return target;
106118
}
107119
@Override
108120
public void releaseTarget(Object target) {
109121
}
110122
};
123+
111124
ProxyFactory pf = new ProxyFactory();
112125
pf.setTargetSource(ts);
113126
Class<?> dependencyType = descriptor.getDependencyType();
114127
if (dependencyType.isInterface()) {
115128
pf.addInterface(dependencyType);
116129
}
117-
return pf.getProxy(beanFactory.getBeanClassLoader());
130+
return pf.getProxy(dlbf.getBeanClassLoader());
118131
}
119132

120133
}

spring-context/src/test/java/org/springframework/context/annotation/LazyAutowiredAnnotationBeanPostProcessorTests.java

Lines changed: 9 additions & 3 deletions
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-2020 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.
@@ -26,9 +26,11 @@
2626
import org.springframework.beans.factory.annotation.Autowired;
2727
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
2828
import org.springframework.beans.factory.config.BeanDefinition;
29+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
2930
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
3031
import org.springframework.beans.factory.support.RootBeanDefinition;
3132
import org.springframework.beans.testfixture.beans.TestBean;
33+
import org.springframework.util.ObjectUtils;
3234

3335
import static org.assertj.core.api.Assertions.assertThat;
3436
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -49,14 +51,18 @@ private void doTestLazyResourceInjection(Class<? extends TestBeanHolder> annotat
4951
ac.registerBeanDefinition("testBean", tbd);
5052
ac.refresh();
5153

54+
ConfigurableListableBeanFactory bf = ac.getBeanFactory();
5255
TestBeanHolder bean = ac.getBean("annotatedBean", TestBeanHolder.class);
53-
assertThat(ac.getBeanFactory().containsSingleton("testBean")).isFalse();
56+
assertThat(bf.containsSingleton("testBean")).isFalse();
5457
assertThat(bean.getTestBean()).isNotNull();
5558
assertThat(bean.getTestBean().getName()).isNull();
56-
assertThat(ac.getBeanFactory().containsSingleton("testBean")).isTrue();
59+
assertThat(bf.containsSingleton("testBean")).isTrue();
5760
TestBean tb = (TestBean) ac.getBean("testBean");
5861
tb.setName("tb");
5962
assertThat(bean.getTestBean().getName()).isSameAs("tb");
63+
64+
assertThat(ObjectUtils.containsElement(bf.getDependenciesForBean("annotatedBean"), "testBean")).isTrue();
65+
assertThat(ObjectUtils.containsElement(bf.getDependentBeans("testBean"), "annotatedBean")).isTrue();
6066
}
6167

6268
@Test

0 commit comments

Comments
 (0)