Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
quaff opened this issue Sep 2, 2019 · 2 comments
Closed
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: regression A bug that is also a regression
Milestone

Comments

@quaff
Copy link
Contributor

quaff commented Sep 2, 2019

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 {

		}

	}
}
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Sep 2, 2019
@quaff
Copy link
Contributor Author

quaff commented Sep 2, 2019

The suspect is beanDefinition.setTargetType(MyService.class).

@quaff quaff changed the title FactoryBean registered by BeanDefinitionRegistryPostProcessor cannot be autowired by type FactoryBean registered with explicit target type cannot be autowired by type Sep 5, 2019
@quaff
Copy link
Contributor Author

quaff commented Sep 5, 2019

@jhoeller It's a regression.

@jhoeller jhoeller self-assigned this Sep 5, 2019
@jhoeller jhoeller added in: core Issues in core modules (aop, beans, core, context, expression) type: regression A bug that is also a regression labels Sep 5, 2019
@jhoeller jhoeller added this to the 5.2 GA milestone Sep 5, 2019
@jhoeller jhoeller removed the status: waiting-for-triage An issue we've not yet triaged or decided on label Sep 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: regression A bug that is also a regression
Projects
None yet
Development

No branches or pull requests

3 participants