Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I name a @Service with multiple names in Spring?

Tags:

spring

I need something like:

@Named({"bean1", "bean2"})

@Service({"bean1", "bean2"})

Can someone help me?

like image 321
Lucas Avatar asked Dec 07 '16 19:12

Lucas


People also ask

Can a Spring bean have multiple names?

Even before the advent of Java configurations, Spring allows a bean to have multiple names using XML configurations. In fact, we can give a bean multiple names by using the name attribute of the bean element.

Can we use @service and @component together?

We can use @Component across the application to mark the beans as Spring's managed components. Spring will only pick up and register beans with @Component, and doesn't look for @Service and @Repository in general. @Service and @Repository are special cases of @Component.

Can we have two beans with same class name?

If you define two beans of same class, without different bean id or qualifiers ( identifier) , Spring container will not be able to understand which bean to be loaded , if you try to access the bean by passing the classname and you will get NoUniqueBeanDefinitionException as there are two qualifying TestBean.

How do you name a component in a Spring?

Let's start with the default naming strategy for an annotation used at the class level. To name a bean, Spring uses the class name and converts the first letter to lowercase. Here, Spring creates a bean for the class LoggingService and registers it using the name “loggingService“.


2 Answers

Though I think @Todd answer is totally correct. It seems it has mislead some others to follow the idea. See Autowire Map with custom class and use aliases to get the correct object reference.

Therefore I would like to add an answer here to suggest one to use the below methodology instead.

@Configuration
public class SampleConfig {
    @Bean(name = {"Service-A", "Service-B", "Service-C"})
    public SampleService createMirroredService() {
        return new SampleService();
    }
}

This would be much cleaner than the above answer, though may not answer the question properly.

like image 134
CHANist Avatar answered Sep 19 '22 16:09

CHANist


Not directly, the way you have it. But it is possible by redefining an existing @Service (or @Component) as a @Bean with either a name or list of names, it is possible.

@Service("Service-A")
public class SampleService {
    public String doSomething() { return "Foo"; }
}

@Configuration
public class SampleConfig {

    @Bean(name = {"Service-B", "Service-C"})
    public SampleService createMirroredService(@Autowired SampleService service) {
        return service;
    }
}

And now you have three instances of SampleService: Service-A (your @Service), Service-B, and Service-C. This works because you define one and just have the @Bean annotated method pass through the implementation, which has the effect of creating aliases. Make sure the configuration class is picked up in the scan and it should work fine.

Note: Although this works, and there are probably other solutions as well, I can't think of a case where I would need this. Perhaps if I'm integrating with a library that already exists that I can't change. But there doesn't strike me as a serious need for this, or else they would have made value on @Component an array.

like image 34
Todd Avatar answered Sep 18 '22 16:09

Todd