【问题标题】:what is the difference between @Bean annotation and @Component annotation at Spring?Spring的@Bean注解和@Component注解有什么区别?
【发布时间】:2019-01-08 21:17:38
【问题描述】:

这对你来说可能是一个非常简单的问题。但是我阅读了很多文档,我完全糊涂了。我们可以使用@Component 代替@Bean 或@Bean 代替@Component(以及@Repository @Service @控制器)?

干杯

【问题讨论】:

标签: spring spring-boot spring-annotations


【解决方案1】:

组件

@Component 也用于 @Service @Repository 用于使用类路径扫描自动检测和自动配置 bean。

只要这些类在我们的基础包下,或者 Spring 知道要扫描另一个包,就会为这些类中的每一个创建一个新的 bean

Bean 和 Component 以一对一的方式映射,即每个类一个 bean。

这些注解 (@Component, @Service, @Repository) 是类级别的注解。

例子:

假设我们有一个 UserService 类,其中包含用户操作的所有方法。

@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 将为 UserService 创建一个 Bean,我们可以在多个位置/类中使用它。

@Bean

@Bean 用于声明单个 bean,而不是像 Component 那样让 Spring 自动完成。

它将 bean 的声明与类定义分离,让您可以完全按照自己的选择创建和配置 bean。

@Bean 用于方法级别,可以根据需要进行配置

例如:

@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;
    }


...

阅读更多关于刻板印象注释here

【讨论】:

    【解决方案2】:

    @Bean 用于将方法定义为生产者,它告诉Spring 使用该方法检索方法返回类型的对象,并在需要时将该对象作为依赖项注入。

    @Component 用于将类定义为Spring 组件,它告诉Spring 创建一个对象(如果它是单例)并处理它的生命周期和依赖关系,并在需要时注入该对象。

    @Service@Repository 基本上就像 @Component 和 AFAIK 一样,它们只是为了更好地对组件进行分组。

    @Service 用于定义具有业务逻辑的服务类,@Repository 用于定义与数据库等底层系统交互的存储库类。

    【讨论】:

      【解决方案3】:

      @组件

      如果我们用 @Component 或其他 Stereotype 注释标记一个类,这些类将使用类路径扫描自动检测。只要这些类在我们的基础包下,或者 Spring 知道要扫描另一个包,就会为这些类中的每一个创建一个新的 bean。

      package com.beanvscomponent.controller;
      
      import org.springframework.stereotype.Controller;
      
      @Controller
      public class HomeController {
      
          public String home(){
             return "Hello, World!";
         }
      
       }
      

      带注释的类和 bean 之间存在隐式的一对一映射(即每个类一个 bean)。这种方法对布线的控制非常有限,因为它纯粹是声明性的。还需要注意的是,构造型注解是类级别的注解。

      @Bean

      @Bean 用于显式声明单个 bean,而不是像我们使用 @Controller 那样让 Spring 自动完成。它将 bean 的声明与类定义分离,并允许您完全按照您的选择创建和配置 bean。使用@Bean,您不会将此注释放在类级别。如果你试图这样做,你会得到一个无效的类型错误。 @Bean 文档将其定义为:

      Indicates that a method produces a bean to be managed by the Spring container.
      

      通常,@Bean 方法是在 @Configuration 类中声明的。我们有一个用户类,我们需要对其进行实例化,然后使用该实例创建一个 bean。这就是我之前所说的,我们对 bean 的定义方式有更多的控制权。

      package com.beanvscomponent;
      
      public class User {
      
      private String first;
      private String last;
      
      public User(String first, String last) {
          this.first = first;
          this.last = last;
         }
      }
      

      正如我之前提到的,@Bean 方法应该在 @Configuration 类中声明。

      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");
         }
      
      }
      

      方法的名称实际上就是我们的 bean 的名称。如果我们在执行器中拉起 /beans 端点,我们可以看到定义的 bean。

      {
      "beans": "superUser",
      "aliases": [],
      "scope": "singleton",
      "type": "com.beanvscomponent.User",
      "resource": "class path resource 
          [com/beanvscomponent/ApplicationConfig.class]",
      "dependencies": []
      }
      

      @Component 与 @Bean

      我希望澄清一些关于何时使用@Component 和何时使用@Bean 的问题。这可能有点令人困惑,但随着您开始编写更多应用程序,它会变得非常自然。

      【讨论】:

        猜你喜欢
        • 2011-10-13
        • 2016-10-31
        • 1970-01-01
        • 1970-01-01
        • 2014-12-29
        • 1970-01-01
        • 2012-08-27
        • 1970-01-01
        相关资源
        最近更新 更多