Why would Spring 3 @Component names clash when they have different packages?

1k views Asked by At

I've got two classes:

package package1;

@Component
public class MyClass1 {
...

package package2;

@Component
public class MyClass1 {
...

When I run failsafe (in maven) - I get the following error in spring (that I don't get in surefire):

test1(package3.MyIntegrationTest)  Time elapsed: 6.737 sec  <<< ERROR!
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by:     org.springframework.context.annotation.ConflictingBeanDefinitionException: 
Annotation-specified bean name 'myClass1' for bean class [packaging1.MyClass1] conflicts 
with existing, non-compatible bean definition of same name and class [package2.MyClass1]

I get that to solve this I could get different Class names - or I could even specify

@Component(name="MyClass1a")

and

@Component(name="MyClass1b")

Or I could even set the package-scan to only package1.

(ie there are three ways to solve this that are obvious - but that's not my question).

That is NOT what I'm asking. (Ie this is not a duplicate).

Now to me - they should only clash in spring if they have the same package name. Surely Spring is smart enough to give them different shortened names if they have different packages?

My question is: Why would Spring 3 @Component names clash when they have different packages?

2

There are 2 answers

0
CollinD On BEST ANSWER

As far as I know, spring's default naming scheme for beans is as follows (see the docs for AnnotationBeanNameGenerator)

package1.MyClass1 -> myClass1
package2.MyClass1 -> myClass1

The package name is stripped, and the first character is lowercased. Only way I know of around this would be to name the beans manually using the optional value of @Component, or via beans.xml or an @Bean annotated config method (or possibly implement your own BeanNameGenerator).

Something to note, inner classes will retain the name of their outer class as part of the bean name since the class shortname is used eg:

package1.MyClass1.MyInnerClass -> myClass1.MyInnerClass

This can cause problems when autowiring by name since the bean name contains a period.

0
Headake On

Without explicit name specification, the detected bean will get a default name derived from the name of its class, without the package name, therefore two beans with the same name would be created which will throw an exception.

You should specify a different name for each @Component if you have multiple classes with the same name.