Spring-framework: Introduce BeanNameGenerator based on fully qualified class name

Created on 2 Dec 2019  路  6Comments  路  Source: spring-projects/spring-framework

Affects: Version 5

@ComponentScan will register Beans with a name generated from the class of the component.

Problem:
Having two classes with the same name UserMapper in different packages will result in an BeanDefinitionStoreException

  1. org.company.dom -> userMapper
  2. org.company.web -> userMapper

Suggestion:
Include the package in the bean name:

  1. org.company.dom.userMapper
  2. org.company.web.userMapper

Why:
I'm forced to duplicate package information in the class name:

  1. org.company.dom; class domUserMapper
  2. org.company.web; class webUserMapper

same giving each Component a package prefixed name:

  1. org.company.dom; @Component("domUserMapper") class userMapper
  2. org.company.web; @Component("webUserMapper") class userMapper

_Especially with generated sources like MapStruct this is not possible._

Or should I write a custom BeanNamingStrategy. For this I do not find so much information, so I guess it's not that famous...

core feedback-provided enhancement

Most helpful comment

Yes, a custom BeanNameGenerator works perfectly. Thank you.

Maybe this would be a good enhancement for the spring-boot project. They could supply a property to choose a custom BeanNameGenerator... So I would save me the boilerplate code (10 Lines) in my main class.

For completness and to help others: This is my current solution:
```java
@SpringBootApplication
@ComponentScan(nameGenerator = CustomGenerator.class)
public class App extends SpringBootServletInitializer {

public static void main(String[] args) {
SpringApplication.run(App.class, args);
}

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application
.sources(App.class);
}

public static class CustomGenerator extends AnnotationBeanNameGenerator {
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return definition.getBeanClassName();
}
}
}

All 6 comments

Implementing a custom BeanNameGenerator is a perfectly viable solution to this kind of problem. I've seen that done in real-world applications.

You can register a custom implementation via @ComponentScan(nameGenerator =...).

Does that meet your needs?

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

Yes, a custom BeanNameGenerator works perfectly. Thank you.

Maybe this would be a good enhancement for the spring-boot project. They could supply a property to choose a custom BeanNameGenerator... So I would save me the boilerplate code (10 Lines) in my main class.

For completness and to help others: This is my current solution:
```java
@SpringBootApplication
@ComponentScan(nameGenerator = CustomGenerator.class)
public class App extends SpringBootServletInitializer {

public static void main(String[] args) {
SpringApplication.run(App.class, args);
}

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application
.sources(App.class);
}

public static class CustomGenerator extends AnnotationBeanNameGenerator {
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return definition.getBeanClassName();
}
}
}

Yes, a custom BeanNameGenerator works perfectly. Thank you.

Great! And... you're welcome.

In light of that, I am closing this issue.

I also see that you raised https://github.com/spring-projects/spring-boot/issues/19346 requesting special support in Spring Boot.

@sbrannen Do you think it's worth surfacing a fully-qualified variant similar ConfigurationClassPostProcessor.IMPORT_BEAN_NAME_GENERATOR that could be generally used?

@philwebb, yes, I think that could be generally useful since I've seen custom ones in the wild a few times.

And you're right: no real need to have ConfigurationClassPostProcessor.IMPORT_BEAN_NAME_GENERATOR defined as an anonymous inner class.

Reopening to see if @jhoeller agrees.

Was this page helpful?
0 / 5 - 0 ratings