diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ContextAnnotationAutowireCandidateResolver.java b/spring-context/src/main/java/org/springframework/context/annotation/ContextAnnotationAutowireCandidateResolver.java index 9d747d0132..93999ddc8c 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ContextAnnotationAutowireCandidateResolver.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ContextAnnotationAutowireCandidateResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,12 +20,14 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Collection; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.springframework.aop.TargetSource; import org.springframework.aop.framework.ProxyFactory; +import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver; import org.springframework.beans.factory.config.DependencyDescriptor; @@ -73,9 +75,11 @@ public class ContextAnnotationAutowireCandidateResolver extends QualifierAnnotat } protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) { - Assert.state(getBeanFactory() instanceof DefaultListableBeanFactory, + BeanFactory beanFactory = getBeanFactory(); + Assert.state(beanFactory instanceof DefaultListableBeanFactory, "BeanFactory needs to be a DefaultListableBeanFactory"); - final DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) getBeanFactory(); + final DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory; + TargetSource ts = new TargetSource() { @Override public Class getTargetClass() { @@ -87,7 +91,8 @@ public class ContextAnnotationAutowireCandidateResolver extends QualifierAnnotat } @Override public Object getTarget() { - Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null); + Set autowiredBeanNames = (beanName != null ? new LinkedHashSet<>(1) : null); + Object target = dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, null); if (target == null) { Class type = getTargetClass(); if (Map.class == type) { @@ -102,19 +107,27 @@ public class ContextAnnotationAutowireCandidateResolver extends QualifierAnnotat throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(), "Optional dependency not present for lazy injection point"); } + if (autowiredBeanNames != null) { + for (String autowiredBeanName : autowiredBeanNames) { + if (dlbf.containsBean(autowiredBeanName)) { + dlbf.registerDependentBean(autowiredBeanName, beanName); + } + } + } return target; } @Override public void releaseTarget(Object target) { } }; + ProxyFactory pf = new ProxyFactory(); pf.setTargetSource(ts); Class dependencyType = descriptor.getDependencyType(); if (dependencyType.isInterface()) { pf.addInterface(dependencyType); } - return pf.getProxy(beanFactory.getBeanClassLoader()); + return pf.getProxy(dlbf.getBeanClassLoader()); } } diff --git a/spring-context/src/test/java/org/springframework/context/annotation/LazyAutowiredAnnotationBeanPostProcessorTests.java b/spring-context/src/test/java/org/springframework/context/annotation/LazyAutowiredAnnotationBeanPostProcessorTests.java index 92f97576e2..8bd05b7e56 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/LazyAutowiredAnnotationBeanPostProcessorTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/LazyAutowiredAnnotationBeanPostProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,9 +26,11 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor; import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.testfixture.beans.TestBean; +import org.springframework.util.ObjectUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -49,14 +51,18 @@ public class LazyAutowiredAnnotationBeanPostProcessorTests { ac.registerBeanDefinition("testBean", tbd); ac.refresh(); + ConfigurableListableBeanFactory bf = ac.getBeanFactory(); TestBeanHolder bean = ac.getBean("annotatedBean", TestBeanHolder.class); - assertThat(ac.getBeanFactory().containsSingleton("testBean")).isFalse(); + assertThat(bf.containsSingleton("testBean")).isFalse(); assertThat(bean.getTestBean()).isNotNull(); assertThat(bean.getTestBean().getName()).isNull(); - assertThat(ac.getBeanFactory().containsSingleton("testBean")).isTrue(); + assertThat(bf.containsSingleton("testBean")).isTrue(); TestBean tb = (TestBean) ac.getBean("testBean"); tb.setName("tb"); assertThat(bean.getTestBean().getName()).isSameAs("tb"); + + assertThat(ObjectUtils.containsElement(bf.getDependenciesForBean("annotatedBean"), "testBean")).isTrue(); + assertThat(ObjectUtils.containsElement(bf.getDependentBeans("testBean"), "annotatedBean")).isTrue(); } @Test