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 9d747d0132c7..93999ddc8c9f 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.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 @@ protected boolean isLazy(DependencyDescriptor descriptor) { } 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 boolean isStatic() { } @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 @@ else if (Set.class == type || Collection.class == type) { 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 3ceb51a23958..b4a2cfa335d9 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-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. @@ -25,9 +25,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.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.tests.sample.beans.TestBean; +import org.springframework.util.ObjectUtils; import static org.junit.Assert.*; @@ -47,14 +49,18 @@ private void doTestLazyResourceInjection(Class annotat ac.registerBeanDefinition("testBean", tbd); ac.refresh(); + ConfigurableListableBeanFactory bf = ac.getBeanFactory(); TestBeanHolder bean = ac.getBean("annotatedBean", TestBeanHolder.class); - assertFalse(ac.getBeanFactory().containsSingleton("testBean")); + assertFalse(bf.containsSingleton("testBean")); assertNotNull(bean.getTestBean()); assertNull(bean.getTestBean().getName()); - assertTrue(ac.getBeanFactory().containsSingleton("testBean")); + assertTrue(bf.containsSingleton("testBean")); TestBean tb = (TestBean) ac.getBean("testBean"); tb.setName("tb"); assertSame("tb", bean.getTestBean().getName()); + + assertTrue(ObjectUtils.containsElement(bf.getDependenciesForBean("annotatedBean"), "testBean")); + assertTrue(ObjectUtils.containsElement(bf.getDependentBeans("testBean"), "annotatedBean")); } @Test