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

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

Closed
spring-projects-issues opened this issue Feb 27, 2009 · 7 comments
Closed
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Feb 27, 2009

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:

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

getBean(Class<T> requiredType) will also need to account for excluding any beans marked as 'primary' from the collection of matching beans.

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

I suppose we'll need to consider providing variants of

containsBean(String)
isSingleton(String)
getBean(String, Object[])

I'm not necessarily advocating that we do, but it should be considered and discussed nonetheless.

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

Suggested JavaDoc:

/**
 * Return an instance, which may be shared or independent, of the specified bean.
 * <p>Behaves the same as {@link #getBean(String)}, but looks the bean up by its
 * type rather than by name.
 * <p>Will ask the parent factory if the bean cannot be found within this factory
 * instance.
 * @param requiredType the type (or any supertype) of the bean to retrieve
 * @return an instance of the bean
 * @throws NoSuchBeanDefinitionException if there's no bean definined matching
 * <var>requiredType</var>
 * @throws AmbiguousBeanLookupException if more than one bean matches
 * <var>requiredType</var>
 * @throws BeansException if the bean could not be created
 */
<T> T getBean(Class<T> requiredType) throws BeansException;

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

A side note: the 'may be shared or independent' language found throughout the JavaDoc in BeanFactory seems to me to be antiquated. I assume this was an early way of referring to singleton and prototype scopes respectively? Let's consider revising/eliminating that phrase altogether.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

We have BeanFactoryUtils.beanOfType(ListableBeanFactory, Class) which is pretty similar. This is the only such method in BeanFactoryUtils that does not simply provide ancestor-traversal behavior on top of ListableBeanFactory... so I suppose it's worth having in the core interfaces. I would add it to ListableBeanFactory, though, since it implies some level of bean definition traversal and matching. We could also call it getBeanOfType, which would nicely match the existing getBeansOfType method in ListableBeanFactory.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Apr 17, 2009

Grzegorz Borkowski commented

Though not directly, but somehow related to it is my request #9787. Perhaps it is also worth considering as candidate to inclusion in Spring 3.0.

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

Note that I've just committed the initial revision of ConfigurationClassApplicationContext, and it contains an implementation of getBean(Class<T> requiredType) as discussed here. When this issue is implemented, we'll simply need to remember to remove this method and rely on the superclass implementation.

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: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants