Spring处的@Bean注解和@Component注解有什么区别?

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

这可能是一个非常简单的问题you.But我阅读了很多文档并且我完全confused.We可以使用@Component而不是@Bean或@Bean而不是@Component(以及作为@Repository @Service @Controller) ?

干杯

@Bean用于定义一个方法作为生产者,它告诉Spring使用该方法获取方法return类型的对象并将该对象作为需要时依赖。

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

@Service@Repository 基本上就像 @Component 和 AFAIK 它们只是为了更好地分组你的组件。

@Service 用于定义您的服务 class 是您拥有业务逻辑的地方,@Repository 用于定义您的存储库 class 是您与底层系统交互的地方像数据库。

组件

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

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

Bean 和组件映射为一对一,即一个 bean 每个 Class。

这些注释(@Component, @Service, @Repository)是Class级注释。

示例:

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

@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,我们可以在多个 location/classes.

处使用它

@Bean

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

它将 bean 的声明与 class 定义分离,并允许您完全按照自己的选择创建和配置 bean。

@Bean在method级别使用,可以按需配置

例如:

@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

@组件

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

package com.beanvscomponent.controller;

import org.springframework.stereotype.Controller;

@Controller
public class HomeController {

    public String home(){
       return "Hello, World!";
   }

 }

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

@豆子

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

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

通常,@Bean 方法在@Configuration classes.We 中声明,有一个用户 class 我们需要实例化然后使用该实例创建一个 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 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");
   }

}

方法的名称实际上将成为我们 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 的问题。这可能有点令人困惑,但随着您开始编写更多应用程序,它会变得很自然。