Skip to content

FactoryBean registered with explicit target type cannot be autowired by type #23561

Closed
@quaff

Description

@quaff

I'm trying upgrade spring from 5.1.4.RELEASE to 5.2.0.RC1, some tests with @Autowired fails caused by NoSuchBeanDefinitionException, I found there is a regression of BeanFactory::getBean(Class<T> requiredType). and use

		@Bean
		public MyServiceFactoryBean MyService() {
			return new MyServiceFactoryBean();
		}

instead of

		@Bean
		public BeanDefinitionRegistryPostProcessor beanDefinitionRegistryPostProcessor() {
			return new MyBeanDefinitionRegistryPostProcessor();
		}

will success.

here is the full test case

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MyTest.MyConfiguration.class)
public class MyTest {

	@Autowired
	DefaultListableBeanFactory beanFactory;

	@Autowired
	MyService myService;

	// @Autowired
	// autowire will fail
	MyServiceFactoryBean MyFactoryBean;

	@Test
	public void testGetBean() throws Exception {
		String beanName = MyService.class.getSimpleName();
		assertThat(beanFactory.getBean(beanName), is(myService));
		assertThat(beanFactory.getBean("&" + beanName), notNullValue());
		assertThat(beanFactory.getBeansOfType(FactoryBean.class).size(), is(1)); // is(0)
		assertThat(beanFactory.getBeansOfType(MyServiceFactoryBean.class).size(), is(1)); // is(0)
		assertThat(beanFactory.getBean(MyServiceFactoryBean.class), notNullValue()); // NoSuchBeanDefinitionException
	}

	static class MyConfiguration {

		@Bean
		public BeanDefinitionRegistryPostProcessor beanDefinitionRegistryPostProcessor() {
			return new MyBeanDefinitionRegistryPostProcessor();
		}
	}

	public interface MyService {

	}

	public static class MyServiceFactoryBean implements FactoryBean<MyService> {

		@Override
		public MyService getObject() throws Exception {
			return new MyService() {
			};
		}

		@Override
		public Class<?> getObjectType() {
			return MyService.class;
		}

	}

	public static class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

		@Override
		public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
			RootBeanDefinition beanDefinition = new RootBeanDefinition(MyServiceFactoryBean.class.getCanonicalName());
			beanDefinition.setPrimary(true);
			beanDefinition.setTargetType(MyService.class);
			beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_NO);
			beanDefinition.setAttribute(getClass().getName(), true);
			registry.registerBeanDefinition(MyService.class.getSimpleName(), beanDefinition);
		}

		@Override
		public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) throws BeansException {

		}

	}
}

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: regressionA bug that is also a regression

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions