Skip to content

Commit 18d90ec

Browse files
committed
Properly handle null FactoryBean instance
Issue: SPR-16250
1 parent d3e0f4d commit 18d90ec

File tree

3 files changed

+32
-19
lines changed

3 files changed

+32
-19
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java

Lines changed: 9 additions & 4 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-2018 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.
@@ -552,7 +552,7 @@ else if (containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
552552

553553
// Check bean class whether we're dealing with a FactoryBean.
554554
if (FactoryBean.class.isAssignableFrom(beanType)) {
555-
if (!BeanFactoryUtils.isFactoryDereference(name)) {
555+
if (!BeanFactoryUtils.isFactoryDereference(name) && beanInstance == null) {
556556
// If it's a FactoryBean, we want to look at what it creates, not the factory class.
557557
beanType = getTypeForFactoryBean(beanName, mbd);
558558
if (beanType == null) {
@@ -1614,8 +1614,13 @@ protected Object getObjectForBeanInstance(
16141614
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
16151615

16161616
// Don't let calling code try to dereference the factory if the bean isn't a factory.
1617-
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
1618-
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
1617+
if (BeanFactoryUtils.isFactoryDereference(name)) {
1618+
if (beanInstance instanceof NullBean) {
1619+
return beanInstance;
1620+
}
1621+
if (!(beanInstance instanceof FactoryBean)) {
1622+
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
1623+
}
16191624
}
16201625

16211626
// Now we have the bean instance, which may be a normal bean or a FactoryBean.

spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java

Lines changed: 17 additions & 14 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-2018 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.
@@ -739,19 +739,22 @@ public void preInstantiateSingletons() throws BeansException {
739739
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
740740
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
741741
if (isFactoryBean(beanName)) {
742-
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
743-
boolean isEagerInit;
744-
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
745-
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) () ->
746-
((SmartFactoryBean<?>) factory).isEagerInit(),
747-
getAccessControlContext());
748-
}
749-
else {
750-
isEagerInit = (factory instanceof SmartFactoryBean &&
751-
((SmartFactoryBean<?>) factory).isEagerInit());
752-
}
753-
if (isEagerInit) {
754-
getBean(beanName);
742+
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
743+
if (bean instanceof FactoryBean) {
744+
final FactoryBean<?> factory = (FactoryBean<?>) bean;
745+
boolean isEagerInit;
746+
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
747+
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) () ->
748+
((SmartFactoryBean<?>) factory).isEagerInit(),
749+
getAccessControlContext());
750+
}
751+
else {
752+
isEagerInit = (factory instanceof SmartFactoryBean &&
753+
((SmartFactoryBean<?>) factory).isEagerInit());
754+
}
755+
if (isEagerInit) {
756+
getBean(beanName);
757+
}
755758
}
756759
}
757760
else {

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

Lines changed: 6 additions & 1 deletion
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-2018 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.
@@ -1132,6 +1132,11 @@ public static class RepositoryFactoryBeanConfiguration {
11321132
public RepositoryFactoryBean<Object> repoFactoryBean() {
11331133
return new RepositoryFactoryBean<>();
11341134
}
1135+
1136+
@Bean
1137+
public FactoryBean<Object> nullFactoryBean() {
1138+
return null;
1139+
}
11351140
}
11361141

11371142
@Configuration

0 commit comments

Comments
 (0)