diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index 8d71720721..fa4a3fca57 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -1134,9 +1134,10 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac * @see #getObjectForBeanInstance */ protected BeanWrapper obtainFromSupplier(Supplier instanceSupplier, String beanName) { + Object instance; + String outerBean = this.currentlyCreatedBean.get(); this.currentlyCreatedBean.set(beanName); - Object instance; try { instance = instanceSupplier.get(); } @@ -1148,6 +1149,10 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac this.currentlyCreatedBean.remove(); } } + + if (instance == null) { + instance = new NullBean(); + } BeanWrapper bw = new BeanWrapperImpl(instance); initBeanWrapper(bw); return bw; diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java index 064f408213..c8f016b9b5 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.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. @@ -286,8 +286,10 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt Assert.state(lo != null, "LookupOverride not found"); Object[] argsToUse = (args.length > 0 ? args : null); // if no-arg, don't insist on args at all if (StringUtils.hasText(lo.getBeanName())) { - return (argsToUse != null ? this.owner.getBean(lo.getBeanName(), argsToUse) : + Object bean = (argsToUse != null ? this.owner.getBean(lo.getBeanName(), argsToUse) : this.owner.getBean(lo.getBeanName())); + // Detect package-protected NullBean instance through equals(null) check + return (bean.equals(null) ? null : bean); } else { return (argsToUse != null ? this.owner.getBean(method.getReturnType(), argsToUse) : diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/LookupAnnotationTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/LookupAnnotationTests.java index b1375d775b..bc18864b19 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/LookupAnnotationTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/LookupAnnotationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 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. @@ -19,6 +19,7 @@ package org.springframework.beans.factory.annotation; import org.junit.Before; import org.junit.Test; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.tests.sample.beans.TestBean; @@ -110,10 +111,23 @@ public class LookupAnnotationTests { assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean); } + @Test // gh-25806 + public void testWithNullBean() { + RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class, () -> null); + tbd.setScope(BeanDefinition.SCOPE_PROTOTYPE); + beanFactory.registerBeanDefinition("testBean", tbd); + + AbstractBean bean = beanFactory.getBean("beanConsumer", BeanConsumer.class).abstractBean; + assertNotNull(bean); + Object expected = bean.get(); + assertNull(expected); + assertSame(bean, beanFactory.getBean(BeanConsumer.class).abstractBean); + } + public static abstract class AbstractBean { - @Lookup + @Lookup("testBean") public abstract TestBean get(); @Lookup