Skip to content

Support BeanFactory#getBean(Class<T> requiredType) [SPR-5529] #10200

Closed
@spring-projects-issues

Description

@spring-projects-issues

Chris Beams opened SPR-5529 and commented

In alignment with Java 5 style and migration of JavaConfig features into core, support the following signature on the BeanFactory interface:

<T> T getBean(Class<T> requiredType) throws BeansException;

This will need to be implemented by the following classes:

AbstractBeanFactory
SimpleJndiBeanFactory
StaticListableBeanFactory
AbstractApplicationContext

There are also several locations throughout the Spring test codebase that call getBean(null). These calls will have to be disambiguated as getBean((String)null).

With the above in mind, the addition of getBean(Class<T>) does introduce a minor backward compatibility issue for anyone calling getBean(null). Given that this is extremely unlikely (because it's meaningless to do so), it's probably not a significant concern.

Implementation approach:

Apply logic similar to that in getBeansOfType(), iterating through all beans, building up a collection of beans that match the given 'requiredType' parameter. If the resulting list contains exactly one bean, return it. If the list contains zero beans, throw a NoSuchBeanDefinitionException. If the list contains more than one matching bean, throw a BeansException specific to the issue. No suitable BeansException currently exists for this, so a suggestion would be 'AmbiguousBeanLookupException extends BeansException' with an appropriate error message, something to the effect of: "3 beans match requested type com.acme.Foo. Consider using getBean(String, Class<T>) to disambiguate. Matching bean names are: ['foo1', 'foo2', 'foo3']

Qualified access by type:

Currently we're supporting <T> T getBean(String, Class<T>). This is a qualification-by-bean-name scenario. We may also want to support qualification-by-@Qualifier. Haven't given much thought to this, but something to the effect of:

<T> T getBean(Class<? extends Annotation> qualifier, Class<T> requiredType)

Such that a client can define two classes of the same supertype:

@Production
@Service
public XyzCustomerService implements CustomerService { ... }

@Testing
@Service
public TestCustomerService implements CustomerService { ... }

Where @Production and @Testing are both meta-annotated as @Qualifier

The user can then register bean definitions for both classes and access the production instance as follows:

ApplicationContext ctx = ...
CustomerService productionInstance = ctx.getBean(Production.class, CustomerService.class);

The latter portion of this issue may well be moved to an issue all its own. Just including it here for completeness & concision.


Issue Links:

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions