Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatically assign spring's bean name to prevent name conflicts?

Tags:

spring

In a spring app , if two programmers develop two packages , annotating @Repository to the same class name , Spring will throw "IllegalStateException" :

Annotation-specified bean name 'mybean' for bean class [foobar.package1.mybean] conflicts with existing, non-compatible bean definition of same name and class [foobar.package2.mybean]

One solution is to add extra value in the @Repository , such as @Repository("package1.mybean") and @Repository("package2.mybean") , but I am looking for a more efficient solution , that can automatically ease such situation . I hope the solution can achieve these goals :

  1. Programmers could arbitrarily name their bean className in his package , regardless of name conflicting with other packages(programmers). So that programmer doesn't need to yell 'Hey , I am going to use bean name XXXXX , don't conflict with me'.

  2. No manually XML bean name assign.

  3. If the bean name can be automatically assigned to the class's full class name , that would be great.

Any ideas ? Thanks. (Spring 3)

like image 957
smallufo Avatar asked Mar 24 '11 02:03

smallufo


2 Answers

Somewhere in your config, you've enabled classpath scanning, probably using

<context:component-scan>

You can specify a property called name-generator, which takes a bean that implements the BeanNameGenerator interface. Create your own implementation of that interface and provide a reference to it.

like image 116
Michal Bachman Avatar answered Nov 14 '22 20:11

Michal Bachman


This is because it is using AnnotationBeanNameGenerator which simply put non-qualified name(class name) as the bean name, then caused conflict.

Two steps to resolve this:

1、You can implement your own bean name generation strategy which use fully-qualified name (package + class name) like below

public class UniqueNameGenerator extends AnnotationBeanNameGenerator {
    @Override
    public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
        //use fully-qualified name as beanName
        String beanName = definition.getBeanClassName();
        return beanName;
    }
}

2、Add @ComponentScan(nameGenerator = UniqueNameGenerator.class) to configuration or Boot class if you are using SpringBoot

@Configuration
@ComponentScan(nameGenerator = UniqueNameGenerator.class)
public class Config {
}
like image 42
Frank Zhang Avatar answered Nov 14 '22 19:11

Frank Zhang