Tonyukuk
Tonyukuk

Reputation: 6195

what is the difference between @Bean annotation and @Component annotation at Spring?

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

Upvotes: 8

Views: 10606

Answers (3)

Partho
Partho

Reputation: 2715

@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

enter image description here

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.

Upvotes: 3

MyTwoCents
MyTwoCents

Reputation: 7624

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.

Upvotes: 15

chubock
chubock

Reputation: 844

@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.

Upvotes: 2

Related Questions