I have a class which I have annotated with #Service #Scope
#Slf4j
#Service
#Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ProductDataModel {
#Value("${message}")
private String message;
The above code seems to be creating a bean for ProductDataModel, without using the #Bean annotation.
I am using #Autowired ProductDataModel productDataModel in my code, and the dependency productDataModel is not null, when used with above piece of Code.
How come the above code is creating bean ??
Ideally, I would have expected bean to created only when I use the below code
//I am not using this piece of code in my program., for reference only
#Configuration
public class OSCConfig {
#Bean
#Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
ProductDataModel productDataModel(){
return new ProductDataModel();
}
Can someone explain the difference between 2 pieces of code and when to use which one.
As #M. Deinum pointed out that we don't need to specify #Bean for each class when we declare #Service or #Controller annotation they are picked up by Spring Container if component-scanning is enabled for that package.
So good use case for using #Bean could be that
If the Class is in third party jar and you can not add #Service/#Controller annotations
If you want to add some custom logic inside the #Bean annotate methods
The #Service annotation is picked up by Spring when scanning for objects to create (as part of a package scan). It is an specialisation of the spring #Component annotation, but doesn't really add much other than providing an indication to users about its intended purpose. The #Controlller annotation is similar, but the bean created has specific characteristics.
The #Bean annotation as you have used it is also used when creating objects, and in this context it is on a method in a Configuration class, therefore the bean created is of the type returned by the method.
Related
It might be a very simple question for you.But I read lots of documents and I am totally confused.We can use #Component instead of #Bean or #Bean instead of #Component(as well as #Repository #Service #Controller) ?
Cheers
Component
#Component also for #Service and #Repository are used to auto-detect and auto-configure beans 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
Bean and Component are mapped as one to one i.e one bean per Class.
These annotations (#Component, #Service, #Repository) are Class level annotations.
Example:
Lets Say we have a UserService Class which contains all methods for User Operation.
#Service
public class UserService {
#Autowired
private UserRepository userRepository;
#Override
public User findByUsername( String username ) throws UsernameNotFoundException {
User u = userRepository.findByUsername( username );
return u;
}
public List<User> findAll() throws AccessDeniedException {
List<User> result = userRepository.findAll();
return result;
}
}
Spring will create a Bean for UserService and we can use this at multiple location/classes.
#Bean
#Bean is used to declare a single bean, rather than letting Spring do it automatically as in case of Component.
It decouples the declaration of the bean from the class definition, and lets you create and configure beans exactly how you choose.
#Bean are used at method level and can be configured as required
eg:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
public SpringTemplateEngine springTemplateEngine()
{
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(htmlTemplateResolver());
return templateEngine;
}
#Bean
public SpringResourceTemplateResolver htmlTemplateResolver()
{
SpringResourceTemplateResolver emailTemplateResolver = new SpringResourceTemplateResolver();
emailTemplateResolver.setPrefix("classpath:/static/template/");
emailTemplateResolver.setSuffix(".html");
emailTemplateResolver.setTemplateMode("HTML");
emailTemplateResolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
return emailTemplateResolver;
}
...
Read more about Stereotype Annotations here.
#Bean is used to define a method as a producer, which tells Spring to use that method to retrieve an object of the method return type and inject that object as a dependency whenever it's required.
#Component is used to define a class as a Spring component, which tells Spring to create an object (if it's Singleton) from and take care of it's lifecycle and dependencies and inject that object whenever it's required.
#Service and #Repository are basically just like #Component and AFAIK they are just for better grouping of your components.
#Service for Defining your service classes where you have your business logic, and #Repository for Defining your repository classes where you interact with an underlying system like database.
#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.
I read about the component scan and as I understood that configuration classes are auto-scanned. my question if I have the following:
#Configuration
public class AppConfig {
#Bean(name="authenticationService")
public AuthenticationService getAuthenticationService(){
return new AuthenticationService();
}
}
if the #Configuration is already scanned (so the app config will be available ), wouldn't be the bean inside it created? I'm little confused as they say the #Bean is not auto scanned
No. Spring won't scan #Bean methods.
Here, you are creating the bean of AuthenticationService just like in any other java program using new keyword.
It is same as AuthenticationService authenticationService = new AuthenticationService();
If you want spring to create a bean of AuthenticationService in AppConfig class, use #Autowired annotation
#Autowired
private AuthenticationService authenticationService;
Hope this helps!
EDIT :
#M.Deinum corrected me that spring doesn't create beans based on #Autowired annotation. Beans are created automatically by spring if their classes are annotated with #Component/ #Configuration / #Service annotations.
#M.Deinum, Thank you.
lets say I have code like this:
#Repository
public class Foo{
}
#Service
public class Boo{
#Autowired
private Foo foo;
}
so now what here are we calling bean? Bean is the object of Foo type of refrence "foo" BUT are Boo class annotated as Service and Foo as Repository ALSO beans? Ihve been using spring for a while now but this basic question makes me feel bad for not knowing...
In the context of Spring, A bean is a spring managed object. Here spring managed means an object created, initialised, managed, destroyed by Spring IoC container.
Whenever we mark a class with #Component, Spring IOC container will create object for your class and manage it, Whenever we can simply get it from ApplicationContext, or access it using #Autowired/#Resource/#Inject annotations
We can also use #Controller, #Repository, #Service, #ControllerAdvice, #Configuration,#Aspect in place of #Component to tell more specifically that our class is a service or a repository or an aspect etc.
We can also use #Bean annotation to create a bean from method return value
#Configuration
public class SolrConfig {
#Value("${spring.data.solr.host}") String solrUrl;
#Bean
public SolrServer solrServer() {
return new HttpSolrServer(solrUrl);
}
#Bean(name = "solrTemplate")
public SolrTemplate solrTemplate() {
return new SolrTemplate(new HttpSolrServer(solrUrl), RULE_ENGINE_CORE);
}
}
All of your application components (#Component, #Service, #Repository, #Controller etc.) will be automatically registered as Spring Beans
http://docs.spring.io/autorepo/docs/spring-boot/current/reference/html/using-boot-spring-beans-and-dependency-injection.html
Defining Beans can be thought of as replacing the keyword new.
Further information can be found here which might be helpful for understanding Beans in Spring.
#ComponentScan creates beans using both #Configuration and #Component. Both these annotations work fine when swapped. What is the difference then?
#Configuration 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
#Component Indicates that an annotated class is a "component". Such
classes are considered as candidates for auto-detection when using
annotation-based configuration and classpath scanning.
#Configuration is meta-annotated with #Component, therefore
#Configuration classes are candidates for component scanning
You can see more here:
http://docs.spring.io/spring-framework/docs/4.0.4.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html
A #Configuration is also a #Component, but a #Component cannot act like a #Configuration.
Actually answer is not complete, is it true that:
#Component Indicates that an annotated class is a "component". Such
classes are considered as candidates for auto-detection when using
annotation-based configuration and classpath scanning.
But you do can create i.e MyConfiguration.java class then stereotype with #Component and add #Beans declaration to it. In this way it will looks as a configuration, main difference is that when annotated class with #Configuration #Bean annotated methods are proxy using CGLIB which made in code calls after the first one to return bean from context instead of execute method again and create another instance as happens when using #Component with #Bean
There is a very subtle difference between them. Let me provide a very quick outlook to this.
Consider the below scenario:
#Configuration
public class MyConfig {
#Bean
public ServiceA aService(){
return new ServiceA();
}
#Bean
public ServiceB bService(){
return new ServiceB(aService());
}
}
Note that ServiceB bean has a dependecy on ServiceA and this is not autowired. Instead, the way it's written implies that a new instance is created, which is not actually created by Spring. You, the programmer, did it with the new keyword instead.
So, if we do use #Configuration, then it uses CGLIB proxying, and in this situation it creates a singleton bean managed by the Spring context. If you invoke it multiple times, it returns the same bean that was created by Spring - sort of autowiring effect.
Whereas if you use #Component, it won't do this proxying and will simply return a new instance every time the method is invoked, instead of providing the Spring managed instance. (Remember that a Spring bean is something that is managed by the Spring container, and, as a developer, it's your job is to pull them in, e.g. with #Autowired.
The same #Component effect can be achieved with #Configuration(proxyEnabled= false) (This is also referred to as bean light mode processing). So, in light mode, you would end up doing something like this:
#Configuration(proxyEnabled = false) // Lite mode, same effect as #Component
public class MyConfig {
#Bean
public ServiceA aService() {
return new ServiceA();
}
#Autowired
#Bean
public ServiceB bService(ServiceA aServiceBean){
return new ServiceB(aServiceBean);
}
}
Refer here for a more elaborate explanation
Hope that helps! Happy Coding!
#Configuration - It is like beans.xml but Java-based bean configuration. It means class annotated with this annotation is the place where beans are configured and will be a candidate for auto-detection. In this class, methods are annotated with #Bean which return an object of the class.
Example:
#Configuration
public class ConfigClass {
#Bean
public UserClass getObject() {
return new UserClass();
}
}
#Component - You cannot autowire (#Autowired) any class if it is not marked with #Component. It means when you want to autowire any class using annotation that class should be annotated with #Component.
Example:
#Component
public class A { .... }
public class B {
#Autowired
A a;
.....
.....
}
Spring Document for reference:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html
#Component is imported by default with #Configuration. controllers, service, and repostory are children components (along with Configuration). They are also candidate for auto-detection.
I am extending on #reus's answer.
#Configuration 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.
If you look at the #Configuration class, you will see that it is meta-annotated with #Component.
#Target(value=TYPE)
#Retention(value=RUNTIME)
#Documented
#Component
public #interface Configuration
#Bean is enables us to define the dependency in any way we like, this is why the #Bean annotation goes above a methods and we manually create a bean object and return it from that method. #Component enables us to define a dependency quickly, that is why #Component goes above classes. We only inject it wherever we need.
Collectively these 3 points says that- to quickly define a bean, we can annotate the class with #Component. To define a bean as we like (support custom requirements), we can write the bean definition using #Bean inside a #Configuration annotated class.
Apart from the differences highlighted by reos.
The reason why #Configuration cannot be replaced by #Component is as below:
The difference is in how the inter bean dependency is handled.
Refer the link for a detailed explanation with example:
Difference between Configuration and Component
I believe #Configuration annotation when used in conjunction with #Bean annotation in spring is used to replace xml configuration. However I saw a piece of code where #Bean was used in conjunction with #Component (defined at class level). Is this a valid declaration? Are there any any pros / cons in using #Component with #Bean annotation vs using #Configuration and #Bean.
EDIT:
Thanks #Sundar & #Biju. I did programmatic call between 2 bean methods under Component class. I saw different object values. However when I used Configuration , I saw the same bean values. Based on what you had explained , I assume a regular method call was made when I used #Component , whereas when I used #Configuration , I assume method annotated with #Bean was treated as a Spring Bean
Code
#Component
public class AppConfig {
#Bean(name="customerService")
public CustomerService getCustomerService(){
System.out.println(getService());
System.out.println(getService());
return getService();
}
#Bean
public CustomerService getService(){
return new CustomerServiceImpl();
}
}
Console Output
com.company.service.CustomerServiceImpl#68bbe345
com.company.service.CustomerServiceImpl#30b8a058
Code
#Configuration
public class AppConfig {
#Bean(name="customerService")
public CustomerService getCustomerService(){
System.out.println(getService());
System.out.println(getService());
return getService();
}
#Bean
public CustomerService getService(){
return new CustomerServiceImpl();
}
}
Console Output
com.company.service.CustomerServiceImpl#71623278
com.company.service.CustomerServiceImpl#71623278
It is a valid declaration, however there are catches - the one within a #Component is referred to as a lite-mode and dependencies cannot easily be injected for beans declared in this form. The recommendation is always to use #Bean in a #Configuration annotated class - here is a good reference on this - http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-java-basic-concepts
You can use #Component as an alternative for #Configuration. It’s official suggestion from spring team.
Simply declare your #Bean methods on classes not annotated with #Configuration (but typically with another Spring stereotype instead, e.g. #Component). As long as you don’t do programmatic calls between your #Bean methods, this is going to work just as fine, but conditions apply*.
Please refer more info in this link.
http://dimafeng.com/2015/08/29/spring-configuration_vs_component/