Using FactoryBean and DisposableBean with Spring's Java Config - java

The ThreadPoolExecutorFactoryBean is a FactoryBean implementing DisposableBean. When being used in Spring's XML bean definition like this
<bean id="executorService"
class="org.springframework.scheduling.concurrent.ThreadPoolExecutorFactoryBean"/>
the created bean will be an instance of ExecutorService and ensures ThreadPoolExecutorFactoryBean#destroy() is called, once the Spring Application Context is shut down.
Is it possible to configure such a bean with a Spring 3's #Configuration class?

I found this approach the most elegant:
#Configuration
public class Cfg {
public ExecutorService executorService() {
return executorServiceFactoryBean().getObject();
}
#Bean
public ThreadPoolExecutorFactoryBean executorServiceFactoryBean() {
return new ThreadPoolExecutorFactoryBean();
}
}
Notice that executorService() is not annotated with #Bean - but you can still call it from other #Bean-methods requiring ExecutorService. Since ThreadPoolExecutorFactoryBean is annotated with #Bean, Spring will automatically manage its lifecycle (detect DisposableBean, etc.)

Related

What's the difference between #Bean and #Component? [duplicate]

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.
#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.
#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.
#Component auto detects and configures the beans using classpath scanning whereas #Bean explicitly declares a single bean, rather than letting Spring do it automatically.
#Component does not decouple the declaration of the bean from the class definition where as #Bean decouples the declaration of the bean from the class definition.
#Component is a class level annotation whereas #Bean is a method level annotation and name of the method serves as the bean name.
#Component need not to be used with the #Configuration annotation where as #Bean annotation has to be used within the class which is annotated with #Configuration.
We cannot create a bean of a class using #Component, if the class is outside spring container whereas we can create a bean of a class using #Bean even if the class is present outside the spring container.
#Component has different specializations like #Controller, #Repository and #Service whereas #Bean has no specializations.
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.
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.
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.
#Bean
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");
#Component
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.
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));
}
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.
Difference between Bean and Component:
#component and its specializations(#Controller, #service, #repository) allow for auto-detection
using classpath scanning. If we see component class like #Controller, #service, #repository will be scan automatically by the spring framework using the component scan.
#Bean on the other hand can only be used to explicitly declare a single bean in a configuration class.
#Bean used to explicitly declare a single bean, rather than letting spring do it automatically. Its make septate declaration of bean from the class definition.
In short #Controller, #service, #repository are for auto-detection and #Bean to create seprate bean from class
- #Controller
public class LoginController
{ --code-- }
- #Configuration
public class AppConfig {
#Bean
public SessionFactory sessionFactory()
{--code-- }
Spring supports multiple types annotations such as #Component, #Service, #Repository. All theses can be found under the org.springframework.stereotype package.
#Bean can be found under the org.springframework.context.annotation package.
When classes in our application are annotated with any of the above mentioned annotation then during project startup spring scan(using #ComponentScan) each class and inject the instance of the classes 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.
#Component
If we mark a class with #Component or one of the other Stereotype annotations these classes will be auto-detected using classpath scanning. As long as these classes are in under our base package or Spring is aware of another package to scan, a new bean will be created for each of these classes.
package com.beanvscomponent.controller;
import org.springframework.stereotype.Controller;
#Controller
public class HomeController {
public String home(){
return "Hello, World!";
}
}
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. It is also important to note that the stereotype annotations are class level annotations.
#Bean
#Bean is used to explicitly declare a single bean, rather than letting Spring do it automatically like we did with #Controller. It decouples the declaration of the bean from the class definition and lets you create and configure beans exactly how you choose. With #Bean you aren't placing this annotation at the class level. If you tried to do that you would get an invalid type error. The #Bean documentation defines it as:
Indicates that a method produces a bean to be managed by the Spring container.
Typically, #Bean methods are declared within #Configuration classes.We have a user class that we needed to instantiate and then create a bean using that instance. This is where I said earlier that we have a little more control over how the bean is defined.
package com.beanvscomponent;
public class User {
private String first;
private String last;
public User(String first, String last) {
this.first = first;
this.last = last;
}
}
As i mentioned earlier #Bean methods should be declared within #Configuration classes.
package com.beanvscomponent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class ApplicationConfig {
#Bean
public User superUser() {
return new User("Partho","Bappy");
}
}
The name of the method is actually going to be the name of our bean. If we pull up the /beans endpoint in the actuator we can see the bean defined.
{
"beans": "superUser",
"aliases": [],
"scope": "singleton",
"type": "com.beanvscomponent.User",
"resource": "class path resource
[com/beanvscomponent/ApplicationConfig.class]",
"dependencies": []
}
#Component vs #Bean
I hope that cleared up some things on when to use #Component and when to use #Bean. It can be a little confusing but as you start to write more applications it will become pretty natural.
#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/
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();
}
}
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.
#Bean can be scoped and #component cannot
such as
#Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)

Injecting #Beans from within a very same #Configuration class idioms

In the past I have seen people using the following 2 idioms to inject dependencies from the same #Configuration:
#Configuration
public class MyConfiguration {
#Bean
public MyBeanDependencyA myBeanDependencyA(){
return new MyBeanDependencyA();
}
#Bean . //IDIOM 1
public MyBeanDependencyB1 myBeanDependencyB1(){
return new MyBeanDependencyB1(myBeanDependencyA());
}
#Bean //IDIOM 2
public MyBeanDependencyB2 myBeanDependencyB2(MyBeanDependencyA myBeanDependencyA){
return new MyBeanDependencyB1(myBeanDependencyA);
}
}
Is there any practical difference between them?
Does Spring process the whole instantiation method in each call for IDIOM 1? (relevant if method has any side-effect, might be not idempotent)?
Does otherwise Spring inject the global managed instance when injecting for IDIOM 1? (relevant If some external process changes the state of the original singleton bean)
Is Spring container that smart?
Does Spring process the whole instantiation method in each call for IDIOM 1? (relevant if method has any side-effect, might be not idempotent)?
By default #Configuration classes are proxied at runtime so the MyBeanDependencyA will be created once and myBeanDependencyA() will be called only once by Spring and next calls will be proxied to return the same instance (as far as example that you shared is concerned). There will be only one instance of this bean in the context as it's scope is Singleton.
Does otherwise Spring inject the global managed instance when injecting for IDIOM 1? (relevant If some external process changes the state of the original singleton bean)
The IOC container will return same instance of Singleton bean when it is queried to do so. Since it is a Singleton all changes to this bean (if it is mutable) will be visible to components that have reference to it.
As a side note you can disable autoproxing of configuration class since Spring 5.2 by using :
#Configuration(proxyBeanMethods = false)
which will prevent proxying calls of methods annotated with #Bean invoked from other #Bean methods.
Does Spring process the whole instantiation method in each call for IDIOM 1?
No, This is called inter-bean dependencies, a method that annotated with #Bean annotation in #Configuration class will create a bean in spring IOC container
The #Bean annotation is used to indicate that a method instantiates, configures and initializes a new object to be managed by the Spring IoC container. For those familiar with Spring's XML configuration the #Bean annotation plays the same role as the element. You can use #Bean annotated methods with any Spring #Component, however, they are most often used with #Configuration beans.
Does otherwise Spring inject the global managed instance when injecting for IDIOM 1?
Yes, spring injects the same bean if it is required at multiple places Basic concepts: #Bean and #Configuration This inter-bean dependencies will only work in combination of #Bean and #Configuration which also prevents calling same bean method multiple times.
Only using #Bean methods within #Configuration classes is a recommended approach of ensuring that 'full' mode is always used. This will prevent the same #Bean method from accidentally being invoked multiple times and helps to reduce subtle bugs that can be hard to track down when operating in 'lite' mode.

Create Spring Components dynamically [duplicate]

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.
#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.
#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.
#Component auto detects and configures the beans using classpath scanning whereas #Bean explicitly declares a single bean, rather than letting Spring do it automatically.
#Component does not decouple the declaration of the bean from the class definition where as #Bean decouples the declaration of the bean from the class definition.
#Component is a class level annotation whereas #Bean is a method level annotation and name of the method serves as the bean name.
#Component need not to be used with the #Configuration annotation where as #Bean annotation has to be used within the class which is annotated with #Configuration.
We cannot create a bean of a class using #Component, if the class is outside spring container whereas we can create a bean of a class using #Bean even if the class is present outside the spring container.
#Component has different specializations like #Controller, #Repository and #Service whereas #Bean has no specializations.
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.
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.
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.
#Bean
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");
#Component
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.
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));
}
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.
Difference between Bean and Component:
#component and its specializations(#Controller, #service, #repository) allow for auto-detection
using classpath scanning. If we see component class like #Controller, #service, #repository will be scan automatically by the spring framework using the component scan.
#Bean on the other hand can only be used to explicitly declare a single bean in a configuration class.
#Bean used to explicitly declare a single bean, rather than letting spring do it automatically. Its make septate declaration of bean from the class definition.
In short #Controller, #service, #repository are for auto-detection and #Bean to create seprate bean from class
- #Controller
public class LoginController
{ --code-- }
- #Configuration
public class AppConfig {
#Bean
public SessionFactory sessionFactory()
{--code-- }
Spring supports multiple types annotations such as #Component, #Service, #Repository. All theses can be found under the org.springframework.stereotype package.
#Bean can be found under the org.springframework.context.annotation package.
When classes in our application are annotated with any of the above mentioned annotation then during project startup spring scan(using #ComponentScan) each class and inject the instance of the classes 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.
#Component
If we mark a class with #Component or one of the other Stereotype annotations these classes will be auto-detected using classpath scanning. As long as these classes are in under our base package or Spring is aware of another package to scan, a new bean will be created for each of these classes.
package com.beanvscomponent.controller;
import org.springframework.stereotype.Controller;
#Controller
public class HomeController {
public String home(){
return "Hello, World!";
}
}
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. It is also important to note that the stereotype annotations are class level annotations.
#Bean
#Bean is used to explicitly declare a single bean, rather than letting Spring do it automatically like we did with #Controller. It decouples the declaration of the bean from the class definition and lets you create and configure beans exactly how you choose. With #Bean you aren't placing this annotation at the class level. If you tried to do that you would get an invalid type error. The #Bean documentation defines it as:
Indicates that a method produces a bean to be managed by the Spring container.
Typically, #Bean methods are declared within #Configuration classes.We have a user class that we needed to instantiate and then create a bean using that instance. This is where I said earlier that we have a little more control over how the bean is defined.
package com.beanvscomponent;
public class User {
private String first;
private String last;
public User(String first, String last) {
this.first = first;
this.last = last;
}
}
As i mentioned earlier #Bean methods should be declared within #Configuration classes.
package com.beanvscomponent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class ApplicationConfig {
#Bean
public User superUser() {
return new User("Partho","Bappy");
}
}
The name of the method is actually going to be the name of our bean. If we pull up the /beans endpoint in the actuator we can see the bean defined.
{
"beans": "superUser",
"aliases": [],
"scope": "singleton",
"type": "com.beanvscomponent.User",
"resource": "class path resource
[com/beanvscomponent/ApplicationConfig.class]",
"dependencies": []
}
#Component vs #Bean
I hope that cleared up some things on when to use #Component and when to use #Bean. It can be a little confusing but as you start to write more applications it will become pretty natural.
#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/
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();
}
}
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.
#Bean can be scoped and #component cannot
such as
#Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)

Spring Boot #Autowired MessageSource works in one classes and doesn't in another

I'm learning Spring boot framework (version 2.0.7.RELEASE) for developing web application. When I try to autowire MessageSource class it works for one classes, but doesn't for another:
Here is my WebConfig class:
package net.local.mis.phog.config;
#Configuration
public class WebConfig implements WebMvcConfigurer {
[...]
#Bean
public MessageSource messageSource() {
// This is the only place around application where messageSource is created
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
[...]
}
Everything works fine in controller classes, for example:
package net.local.mis.phog.controller;
#Controller
#Transactional
public class AlbumController {
[...]
#Autowired
private MessageSource messageSource; (works fine)
[...]
}
But when I try to inject messagSource in model classes it failes:
package net.local.mis.phog.model;
#Component
public class AlbumModel {
[...]
#Autowired
private MessageSource messageSource; (null)
[...]
}
In spring - component autowired in one class but not in another Balaji Krishnan says: "You are not using spring to obtain Account instance - so spring did not get a chance to autowire it". Perhaps I should do something of the kind, but I cannot understand how.
Can anybody please help me.
Thank you, Mikhail.
For spring to leverage dependency injection, the beans must all be managed by spring. The AlbumModel object creation should be managed by spring, so that the MessageSource can be autowired. If AlbumModel should not be managed by spring and you want to create the object yourself (which I doubt because you annotated it with #Component) then you could also use constructor injection.
Whereas you can have something like this:
package net.local.mis.phog.model;
#Component
public class AlbumModel {
[...]
private MessageSource messageSource;
[...]
#Autowired
public AlbumModel(MessageSource messageSource) {
this.messageSource = messageSource;
}
}
With the solution above, when you manually create an AlbumModel, you could pass in the MessageSource object, which is already autowired by the calling class (for example the controller or any service layer class). But also when AlbumModel creation is manage by spring it is advisable to use constructor injection. Read more about it on an article by a Spring contributor
Thank you guys for your answers.
Amit Bera, I create AlbumModel object just by calling its constructor:
package net.local.mis.phog.controller;
#Controller
#Transactional
public class AlbumController {
[...]
#Autowired
private JenreDao jenreDao;
#Autowired
private MessageSource messageSource;
[...]
#RequestMapping(value={"/album"},method=RequestMethod.GET)
public String albumShowHandler(Model model,
HttpServletRequest request,
#RequestParam(value="jenreIdSelected") Long jenreIdSelected,
#CookieValue(value="thumbnailOrder",defaultValue="ordDefault") String thumbnailOrder,
[...]) {
[...]
ThumbnailOrderAux thumbnailOrderAux = new ThumbnailOrderAux(thumbnailOrder);
JenreAux jenreAux = new JenreAux(jenreDao.getLstJenreModel(null,jenreIdSelected),jenreIdSelected);
AlbumModel albumModel = new AlbumModel(jenreAux,thumbnailOrderAux);
[...]
model.addAttribute("albumModel",albumModel);
return "album";
}
[...]
}
And here is code of AdminModel constructors:
package net.local.mis.phog.model;
#Component
public class AlbumModel {
private JenreAux jenreAux;
private ThumbnailAux thumbnailAux;
[...]
public AlbumModel() {
super();
}
public AlbumModel(JenreAux jenreAux,ThumbnailOrderAux thumbnailOrderAux) {
super();
this.jenreAux = jenreAux;
this.thumbnailOrderAux = thumbnailOrderAux;
}
[...]
}
Nazeem, I added #Component annotation to AlbumModel class in hope that MessageSource bean would be injected. Unfortunately it was not.
I could pass MessageSource as argument and it works even if I don't annotate constructor #Autowired. If I understand it right MessageSource bean is injected to AlbumController because it managed by Spring, and it isn't injected to AlbumModel because it doesn't managed by Spring. Right? If so, is there any way I make Spring manage AlbumModel object?
I had the same problem on a spring 3.1.1-RELEASE old application. In my case during debug I've got two different MessageResource objects as if the wold have been instanziated twice.
I've solved moving the bean definition:
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
from dispatcher-servlet.xml xml-based configuration file to the applicationContext.xml ones.
In other words, there exists two contexts: the application context and the dispatcher servlet contexts. The application context is the parent of the dispatcher servlet context (I guess that many servlet contexts may exists under the same application context if your application consists of many servlet).
Thus, beans defined in the application context are visible to the servlet context, but not vice versa. While the servlet context contains those beans that are specifically related to MVC, the application context is used to define broader beans like services.
Since #Controller annotation is a #Component annotated ones:
#Component
public #interface Controller
i guess Spring autowires beans in #Controller and #Component differently, looking for beans in the two different contexts mentioned above.

Java #Component class and #Configuration class with AnnotationConfigApplicationContext

I know springs AnnotationConfigApplicationContext is capable of accepting not only #Configuration classes as input but also plain #Component classes and classes annotated with JSR-330 metadata.
I have created AppConfig.java below without #Configuration annotation.
public class AppConfig {
#Bean(name="sampleService")
public SampleService getSampleService(){
return new SampleService();
}
}
Passed this class as my java config class to AnnotationConfigApplicationContext, it accepted and registered my service beans.
I did some modification on above same AppConfig like below.
#Component
public class AppConfig {
#Bean(name="sampleService")
public SampleService getSampleService(){
return new SampleService();
}
}
passed AppConfig to AnnotationConfigApplicationContext, it accepted and registered my service beans.
Question:
AnnotationConfigApplicationContext class is accepting the java config class with #Configuration, without #Configuration and with #Component annotations, what is the difference between #Component and #Configuration?
Why is it Accepting even without #Configuration annotation?
When to use #Configuration, and when to use #Component as java config class?
#Component
Indicates that an annotated class is a "component".
That is, in a context where component scanning is enabled, Spring generates bean definitions for #Component annotated types. These bean definitions end up being turned into beans.
#Configuration, which is itself annotated with
Indicates that a class declares one or more #Bean methods and may be
processed by the Spring container to generate bean definitions and
service requests for those beans at runtime, [...]
So any #Configuration type, for which Spring generates a bean, acts as a factory for beans.
The javadoc of #Bean states
#Bean methods may also be declared within classes that are not
annotated with #Configuration. For example, bean methods may be
declared in a #Component class or even in a plain old class. In such
cases, a #Bean method will get processed in a so-called 'lite' mode.
Bean methods in lite mode will be treated as plain factory methods by
the container (similar to factory-method declarations in XML), with
scoping and lifecycle callbacks properly applied. The containing class
remains unmodified in this case, and there are no unusual constraints
for the containing class or the factory methods.
In contrast to the semantics for bean methods in #Configuration
classes, 'inter-bean references' are not supported in lite mode.
Instead, when one #Bean-method invokes another #Bean-method in lite
mode, the invocation is a standard Java method invocation; Spring does
not intercept the invocation via a CGLIB proxy. This is analogous to
inter-#Transactional method calls where in proxy mode, Spring does not
intercept the invocation — Spring does so only in AspectJ mode.
So #Bean methods have full functionality in #Configuration annotated classes and limited functionality in #Component annotated classes.
why it is Accepting even without #Configuration annotation?
That's how the class is designed. An ApplicationContext is a BeanFactory. AnnotationConfigApplicationContext simply offers an extra way to register a bean definition.
When to use #Configuration, and when to use #Component as java config class?
These really completely separate goals. Follow the javadoc. When you need to setup an ApplicationContext, you can use an AnnotationConfigApplicationContext with a #Configuration annotated class. If you simply need a bean, annotate its type with #Component.
#Component annotation marks the Java class as a bean, but #Configuration annotation marks the Java class containing beans (methods that have #Bean annotation).
The #Bean annotation must use with #Configuration exactly to create Spring
beans.
In following class
#Component
public class AppConfig {
#Bean(name="sampleService")
public SampleService getSampleService(){
return new SampleService();
}
}
#Bean annotation is not any effect, and getSampleService() method will be plain old java method and will not be singleton, because as i mentioned, #Bean annotation must use with #Configuration, so it must be repaired as following:
#Configuration
public class AppConfig {
#Bean(name="sampleService")
public SampleService getSampleService(){
return new SampleService();
}
}
so replacing #Configuration annotation with any other annotation, or removing it, just make #Bean annotation ineffective and getSampleService() method will not be singleton anymore.

Categories