I understand that @Component
annotation was introduced in spring 2.5 in order to get rid of xml bean definition by using classpath scanning.
@Bean
was introduced in spring 3.0 and can be used with @Configuration
in order to fully get rid of xml file and use java config instead.
Would it have been possible to re-use the @Component
annotation instead of introducing @Bean
annotation? My understanding is that the final goal is to create beans in both cases.
This question is related to
java
spring
annotations
autowired
You have two ways to generate beans.
One is to create a class with an annotation @Component
.
The other is to create a method and annotate it with @Bean
. For those classes containing method with @Bean
should be annotated with @Configuration
Once you run your spring project, the class with a @ComponentScan
annotation would scan every class with @Component
on it, and restore the instance of this class to the Ioc Container. Another thing the @ComponentScan
would do is running the methods with @Bean
on it and restore the return object to the Ioc Container as a bean.
So when you need to decide which kind of beans you want to create depending upon current states, you need to use @Bean
. You can write the logic and return the object you want.
Another thing worth to mention is the name of the method with @Bean
is the default name of bean.
@Bean was created to avoid coupling Spring and your business rules in compile time. It means you can reuse your business rules in other frameworks like PlayFramework or JEE.
Moreover, you have total control on how create beans, where it is not enough the default Spring instantation.
I wrote a post talking about it.
https://coderstower.com/2019/04/23/factory-methods-decoupling-ioc-container-abstraction/
Additional Points from above answers
Let’s say we got a module which is shared in multiple apps and it contains a few services. Not all are needed for each app.
If use @Component on those service classes and the component scan in the application,
we might end up detecting more beans than necessary
In this case, you either had to adjust the filtering of the component scan or provide the configuration that even the unused beans can run. Otherwise, the application context won’t start.
In this case, it is better to work with @Bean annotation and only instantiate those beans,
which are required individually in each app
So, essentially, use @Bean for adding third-party classes to the context. And @Component if it is just inside your single application.
@Component Preferable for component scanning and automatic wiring.
When should you use @Bean?
Sometimes automatic configuration is not an option. When? Let's imagine that you want to wire components from 3rd-party libraries (you don't have the source code so you can't annotate its classes with @Component), so automatic configuration is not possible.
The @Bean annotation returns an object that spring should register as bean in application context. The body of the method bears the logic responsible for creating the instance.
Both approaches aim to register target type in Spring container.
The difference is that @Bean
is applicable to methods, whereas @Component
is applicable to types.
Therefore when you use @Bean
annotation you control instance creation logic in method's body (see example above). With @Component
annotation you cannot.
1. About @Component
@Component functs similarily to @Configuration.
They both indicate that the annotated class has one or more beans need to be registered to Spring-IOC-Container
.
The class annotated by @Component, we call it Component of Spring
. It is a concept that contains several beans.
Component class
needs to be auto-scanned by Spring for registering those beans of the component class
.
2. About @Bean
@Bean is used to annotate the method of component-class
(as mentioned above). It indicate the instance retured by the annotated method needs to be registered to Spring-IOC-Container
.
3. Conclusion
The difference between them two is relatively obivious, they are used in different circumstances
.
The general usage is:
// @Configuration is implemented by @Component
@Configuration
public ComponentClass {
@Bean
public FirstBean FirstBeanMethod() {
return new FirstBean();
}
@Bean
public SecondBean SecondBeanMethod() {
return new SecondBean();
}
}
Let's consider I want specific implementation depending on some dynamic state.
@Bean
is perfect for that case.
@Bean
@Scope("prototype")
public SomeService someService() {
switch (state) {
case 1:
return new Impl1();
case 2:
return new Impl2();
case 3:
return new Impl3();
default:
return new Impl();
}
}
However there is no way to do that with @Component
.
When you use the @Component
tag, it's the same as having a POJO (Plain Old Java Object) with a vanilla bean declaration method (annotated with @Bean
). For example, the following method 1 and 2 will give the same result.
Method 1
@Component
public class SomeClass {
private int number;
public SomeClass(Integer theNumber){
this.number = theNumber.intValue();
}
public int getNumber(){
return this.number;
}
}
with a bean for 'theNumber':
@Bean
Integer theNumber(){
return new Integer(3456);
}
Method 2
//Note: no @Component tag
public class SomeClass {
private int number;
public SomeClass(Integer theNumber){
this.number = theNumber.intValue();
}
public int getNumber(){
return this.number;
}
}
with the beans for both:
@Bean
Integer theNumber(){
return new Integer(3456);
}
@Bean
SomeClass someClass(Integer theNumber){
return new SomeClass(theNumber);
}
Method 2 allows you to keep bean declarations together, it's a bit more flexible etc. You may even want to add another non-vanilla SomeClass bean like the following:
@Bean
SomeClass strawberryClass(){
return new SomeClass(new Integer(1));
}
@Component
and @Bean
do two quite different things, and shouldn't be confused.
@Component
(and @Service
and @Repository
) are used to auto-detect and auto-configure beans using classpath scanning. There's an implicit one-to-one mapping between the annotated class and the bean (i.e. one bean per class). Control of wiring is quite limited with this approach, since it's purely declarative.
@Bean
is used to explicitly declare a single bean, rather than letting Spring do it automatically as above. It decouples the declaration of the bean from the class definition, and lets you create and configure beans exactly how you choose.
To answer your question...
would it have been possible to re-use the
@Component
annotation instead of introducing@Bean
annotation?
Sure, probably; but they chose not to, since the two are quite different. Spring's already confusing enough without muddying the waters further.
- @Controller public class LoginController { --code-- } - @Configuration public class AppConfig { @Bean public SessionFactory sessionFactory() {--code-- }
I see a lot of answers and almost everywhere it's mentioned @Component
is for autowiring where component is scanned, and @Bean
is exactly declaring that bean to be used differently. Let me show how it's different.
First it's a method level annotation.
Second you generally use it to configure beans in Java code (if you are not using xml configuration) and then call it from a class using the
ApplicationContext.getBean
method. Example:
@Configuration
class MyConfiguration{
@Bean
public User getUser() {
return new User();
}
}
class User{
}
// Getting Bean
User user = applicationContext.getBean("getUser");
It is the general way to annotate a bean and not a specialized bean. It is a class level annotation and is used to avoid all that configuration stuff through java or xml configuration.
We get something like this.
@Component
class User {
}
// to get Bean
@Autowired
User user;
That's it. It was just introduced to avoid all the configuration steps to instantiate and use that bean.
You can use @Bean
to make an existing third-party class available to your Spring framework application context.
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
By using the @Bean
annotation, you can wrap a third-party class (it may not have @Component
and it may not use Spring), as a Spring bean. And then once it is wrapped using @Bean
, it is as a singleton object and available in your Spring framework application context. You can now easily share/reuse this bean in your app using dependency injection and @Autowired
.
So think of the @Bean
annotation is a wrapper/adapter for third-party classes. You want to make the third-party classes available to your Spring framework application context.
By using @Bean
in the code above, I'm explicitly declare a single bean because inside of the method, I'm explicitly creating the object using the new
keyword. I'm also manually calling setter methods of the given class. So I can change the value of the prefix field. So this manual work is referred to as explicit creation. If I use the @Component
for the same class, the bean registered in the Spring container will have default value for the prefix field.
On the other hand, when we annotate a class with @Component
, no need for us to manually use the new
keyword. It is handled automatically by Spring.
Source: Stackoverflow.com