joerg.hohwiller@googlemail.com opened SPR-15883 and commented

FactoryBean can only be used if the type of the bean to create is known before. As your BeanFactory offers a method <T> T getBean(Class<T> requiredType) I would expect to see a way to register one or multiple instances of a new factory bean interface that would be used as fallback if no bean is already present and also no concrete factory is available. With fallback I mean that before spring is actually comming to the conclusion that it should throw an exception telling that there is no such bean, it could traverse a list of potential implementations of that new interface and delegate the fabrication to that interface before giving up and throwing the exception. IMHO this could be easily added as a new feature without breaking compatibility if you know the right magic spot in the spring core code. In case you agree and give a slight hint I would even try to create a PR.

Without such generic factory bean the only suitable case seems to be a classpath scanning during the bootstrap (what e.g. spring-data is doing). IMHO it is not a good idea to have multiple "solutions" hooked up into spring that rely on such classpath scanning. Due to the support for classpath scanning offered by spring itself this does not even cache work that has already been done before. In the end this all results in bad bootstrapping performance. I really searched deep and found things like #19149 but still this does not solve my problem. My usecase is that e.g. in case you have a marker interface called Service that you may configure spring in a way so that if a concrete sub-interface MyFooService is injected then my generic custom factory bean could be invoked from BeanFactory and would create a client stub for that service including service discovery, etc. I already have created such client stub factory for REST and SOAP services as open-source: https://github.com/hohwille/oasp4j/blob/develop/modules/service/src/main/java/io/oasp/module/service/common/api/client/ServiceClientFactory.java All I need is a way to integrate this with spring to even lower the burden of actually creating the client stub for every usage as an advanced and optional use-case on top of this. However, there are tons of other use-cases for this need.

I love to hear from you and say thanks in advance for considering my proposal. In case this feature is already available and I have missed it then I apologize and you can close this issue with a simple link on the docs (but I really looked everywhere I could imagine).


Reference URL: https://stackoverflow.com/questions/44495708/dynamic-spring-factory-to-create-a-bean-requested-by-its-given-type

2 votes, 3 watchers

Comment From: spring-projects-issues

joerg.hohwiller@googlemail.com commented

This is closely related to #20896. Maybe that could also be considered as duplicate.

Comment From: spring-projects-issues

joerg.hohwiller@googlemail.com commented

Still hoping for feedback. IMHO this would be a reasonable and valuable extension to spring-core. If you agree I would be up to create a PR for you if you like.

Comment From: Frettman

A FactoryBean that doesn't just handle X but every type that extends or implements X would also solve my problem. I don't want to explicitly declare each object as bean that someone might want to inject, because that would involve classpath scanning and - at least in my mind - pollute the application context with potentially a lot of beans that might never be used. That's why I would like to create them on demand at injection-time. There's the option of creating a FactoryBean<?/Object> that seems to be called for almost everything. Using an InjectionPoint it's possible to decide whether the requested bean is something I want to handle myself or whether to fallback to default behavior.

@Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public FactoryBean<?> messageProxyFactory(DependencyDescriptor injectionPoint)

Unfortunately, FactoryBean<?> and InjectionPoint seems to be an impossible combinaton, as the InjectionPoint parameter is considered mandatory and e.g. ´BeanFactory#getBean(...)` simply does not provide an InjectionPoint. As such there will always be an error at some point. So far, I couldn't find a way to narrow the FactoryBean back down using some other means, like @Qualifier.

Comment From: snicoll

I don't really see an answer to what you're trying to do using the core container. If you want to produce any bean of type with some sort of fallback mechanism, I'd create a factory (that is a bean) and let that creates beans accordingly, potentially honoring some lifecycle if necessary.

Getting in a state where we don't know the beans that are going to be handled by the application context leads to other issues that will make things inconsistent (by type injection, typically).