Reputation: 10989
I'm just learning spring, and something struck me as very odd about the annotation configurations using the name
attribute as a string.
@Bean(name = "com.my.injected.Service")
public InjectedService injectedService() {
return injectedService;
}
Is this name similar to the Spring Bean XML configuration id
and class
attributes?
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
Why isn't this simply
@Bean(clazz = com.my.injected.Service.class)
public InjectedService injectedService() {
return injectedService;
}
instead?
You're fully qualifying the path in both cases and actually using the class makes it way easier for your IDE to tell you when you've screwed it up. I understand that the XML configuration came first, and naturally it was always looking up things by string, so is this just a holdover? Is there some advantage to using strings or major disadvantage to using .class
?
Question was originally based on a false premise. I edited it to spell out what this premise was and make it less confusing for new people who come along. Hopefully I did this such that the given answers are still exactly applicable; apologies if not.
Upvotes: 0
Views: 4119
Reputation: 115328
Bean name is not necessarily related to its class or even any of interfaces it implements. It is a name and nothing more. When you use the annotation configuration, Spring figures out what the exact class or interface the @Bean
provides like the rest of java code would: either through the fully qualified name in the code or through the imports specified in the file. In your case, you presumably have an import com.my.injected.Service;
statement at the top of the java file.
Your example is using the fully qualified class name as the bean name. It is your choice. You could use any other identifier. Using the fully qualified name could be useful if your code is providing an object that is named exactly like another 3rd party @Bean
object that your code must include or consume. However, you could just as easily use name = "myService"
.
The bean name helps Spring (and application programmer) to distinguish between multiple instances of of the same bean class because you can deploy the same class as bean several times. If only one instance of bean type appear you event do not have to give it name manually: spring does this by default.
If you have several beans that have the same type or implement the same interface and you want to refer specific bean use @Qualifier
annotation.
Upvotes: 1
Reputation: 85781
@Bean
annotation is meant to provide a spring bean. The type of the bean to provide will be the same type of the class/interface you define in the return method. So, instead of declaring to return a concrete class in the method, return the top (abstract) class/interface instead.
Imagine this case:
public interface MyEntityDao {
MyEntity get(String id);
}
@Repository
public class MyEntityDaoDatabaseImpl implements MyEntityDao {
@Override
public MyEntity get(String id) {
/* implementation that goes to database every time */
}
}
@Repository
public class MyEntityDaoCacheImpl implements MyEntityDao {
@Override
public MyEntity get(String id) {
/* implementation that looks the data
up in cache, never in database */
}
}
@Configuration
public class MyAppConfiguration {
@Bean
public MyEntityDaoDatabaseImpl method1() {
return new MyEntityDaoDatabaseImpl();
}
@Bean
public MyEntityDaoCacheImpl method2() {
return new MyEntityDaoCacheImpl();
}
}
@Service
public class MyEntityService {
@Autowired //what to inject here?
MyEntityDao dao;
}
In case above, there are two implementations of the proposed interface. How the framework may be able to understand which implementation to use except for the name?
@Service
public class MyEntityService {
@Autowired
@Qualifier("properBeanNameToInject")
MyEntityDao dao;
}
Upvotes: 2