Skip to content

Commit 265bc6c

Browse files
committed
Populate dependencies metadata for resolved target behind lazy dependency proxy
Closes gh-25562
1 parent 3d2de9a commit 265bc6c

File tree

2 files changed

+30
-11
lines changed

2 files changed

+30
-11
lines changed

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

Lines changed: 21 additions & 8 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;
@@ -71,9 +73,11 @@ protected boolean isLazy(DependencyDescriptor descriptor) {
7173
}
7274

7375
protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final String beanName) {
74-
Assert.state(getBeanFactory() instanceof DefaultListableBeanFactory,
76+
BeanFactory beanFactory = getBeanFactory();
77+
Assert.state(beanFactory instanceof DefaultListableBeanFactory,
7578
"BeanFactory needs to be a DefaultListableBeanFactory");
76-
final DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) getBeanFactory();
79+
final DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory;
80+
7781
TargetSource ts = new TargetSource() {
7882
@Override
7983
public Class<?> getTargetClass() {
@@ -85,34 +89,43 @@ public boolean isStatic() {
8589
}
8690
@Override
8791
public Object getTarget() {
88-
Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null);
92+
Set<String> autowiredBeanNames = (beanName != null ? new LinkedHashSet<String>(1) : null);
93+
Object target = dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, null);
8994
if (target == null) {
9095
Class<?> type = getTargetClass();
9196
if (Map.class == type) {
92-
return Collections.EMPTY_MAP;
97+
return Collections.emptyMap();
9398
}
9499
else if (List.class == type) {
95-
return Collections.EMPTY_LIST;
100+
return Collections.emptyList();
96101
}
97102
else if (Set.class == type || Collection.class == type) {
98-
return Collections.EMPTY_SET;
103+
return Collections.emptySet();
99104
}
100105
throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),
101106
"Optional dependency not present for lazy injection point");
102107
}
108+
if (autowiredBeanNames != null) {
109+
for (String autowiredBeanName : autowiredBeanNames) {
110+
if (dlbf.containsBean(autowiredBeanName)) {
111+
dlbf.registerDependentBean(autowiredBeanName, beanName);
112+
}
113+
}
114+
}
103115
return target;
104116
}
105117
@Override
106118
public void releaseTarget(Object target) {
107119
}
108120
};
121+
109122
ProxyFactory pf = new ProxyFactory();
110123
pf.setTargetSource(ts);
111124
Class<?> dependencyType = descriptor.getDependencyType();
112125
if (dependencyType.isInterface()) {
113126
pf.addInterface(dependencyType);
114127
}
115-
return pf.getProxy(beanFactory.getBeanClassLoader());
128+
return pf.getProxy(dlbf.getBeanClassLoader());
116129
}
117130

118131
}

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-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.
@@ -25,9 +25,11 @@
2525
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
2626
import org.springframework.beans.factory.annotation.Autowired;
2727
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
28+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
2829
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
2930
import org.springframework.beans.factory.support.RootBeanDefinition;
3031
import org.springframework.tests.sample.beans.TestBean;
32+
import org.springframework.util.ObjectUtils;
3133

3234
import static org.junit.Assert.*;
3335

@@ -47,14 +49,18 @@ private void doTestLazyResourceInjection(Class<? extends TestBeanHolder> annotat
4749
ac.registerBeanDefinition("testBean", tbd);
4850
ac.refresh();
4951

52+
ConfigurableListableBeanFactory bf = ac.getBeanFactory();
5053
TestBeanHolder bean = ac.getBean("annotatedBean", TestBeanHolder.class);
51-
assertFalse(ac.getBeanFactory().containsSingleton("testBean"));
54+
assertFalse(bf.containsSingleton("testBean"));
5255
assertNotNull(bean.getTestBean());
5356
assertNull(bean.getTestBean().getName());
54-
assertTrue(ac.getBeanFactory().containsSingleton("testBean"));
57+
assertTrue(bf.containsSingleton("testBean"));
5558
TestBean tb = (TestBean) ac.getBean("testBean");
5659
tb.setName("tb");
5760
assertSame("tb", bean.getTestBean().getName());
61+
62+
assertTrue(ObjectUtils.containsElement(bf.getDependenciesForBean("annotatedBean"), "testBean"));
63+
assertTrue(ObjectUtils.containsElement(bf.getDependentBeans("testBean"), "annotatedBean"));
5864
}
5965

6066
@Test

0 commit comments

Comments
 (0)