我知道在 spring 2.5 中引入了 @Component
注释,以便通过使用类路径扫描来摆脱 xml bean 定义。
@Bean
是在 spring 3.0 中引入的,可以与 @Configuration
一起使用,以便完全摆脱 xml 文件并改用 java config。
是否可以重复使用 @Component
注释而不是引入 @Bean
注释?我的理解是最终目标是在这两种情况下创建 bean。
Lite mode
。而且不推荐。见这里:docs.spring.io/spring/docs/current/spring-framework-reference/…
@bean
的方法返回一个可自定义的 spring bean 实例,而 @component
定义了一个类,稍后可能在需要时由 spring IoC 引擎实例化。
@Bean
可以在用 @Component
注释的类中使用。 “您可以在 @Configuration-annotated 或 @Component-annotated 类中使用 @Bean 注解。” docs.spring.io/spring-framework/docs/current/reference/html/…
@Component 首选用于组件扫描和自动布线。
什么时候应该使用@Bean?
有时自动配置不是一种选择。什么时候?假设您想从 3rd-party 库中连接组件(您没有源代码,因此无法使用 @Component 注释其类),因此无法进行自动配置。
@Bean 注解返回一个对象,spring 应该在应用程序上下文中注册为 bean。方法的主体包含负责创建实例的逻辑。
@Component
和 @Bean
做两件完全不同的事情,不应混淆。
@Component
(以及 @Service
和 @Repository
)用于使用类路径扫描自动检测和自动配置 bean。带注释的类和 bean 之间存在隐式的一对一映射(即每个类一个 bean)。这种方法对布线的控制非常有限,因为它纯粹是声明性的。
@Bean
用于显式声明单个 bean,而不是像上面那样让 Spring 自动完成。它将 bean 的声明与类定义分离,并允许您完全按照您的选择创建和配置 bean。
要回答你的问题...
是否可以重用@Component 注释而不是引入@Bean 注释?
当然,可能;但他们选择不这样做,因为两者完全不同。春天已经足够混乱,没有进一步搅浑水。
@Component
吗?似乎 @Bean
不能影响 @Autowired
@Configuration
注释了您的 bean 类,您可以将 @Autowired
与 @Bean
一起使用
让我们考虑一下我想要根据某些动态状态的具体实现。 @Bean
非常适合这种情况。
@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();
}
}
但是,@Component
无法做到这一点。
@Configuration
注释
@Component 使用类路径扫描自动检测和配置 bean,而 @Bean 显式声明单个 bean,而不是让 Spring 自动执行。 @Component 不会将 bean 的声明与类定义分离,而 @Bean 将 bean 的声明与类定义分离。 @Component 是一个类级别的注解,而 @Bean 是一个方法级别的注解,方法的名称作为 bean 的名称。 @Component 不需要与@Configuration 注释一起使用,而@Bean 注释必须在使用@Configuration 注释的类中使用。如果类在 Spring 容器之外,我们不能使用 @Component 创建类的 bean,而我们可以使用 @Bean 创建类的 bean,即使该类存在于 Spring 容器之外。 @Component 具有不同的特化,例如 @Controller、@Repository 和 @Service,而 @Bean 没有特化。
这两种方法都旨在在 Spring 容器中注册目标类型。
不同之处在于 @Bean
适用于方法,而 @Component
适用于 types。
因此,当您使用 @Bean
注释时,您可以控制方法主体中的实例创建逻辑(请参阅 example above)。使用 @Component
注释你不能。
Dog rex = new Dog()
,则名为“rex”的对象属于“Dog”类型,因为它是“Dog”类的一个实例。
@ConditionalOnBean(SomeBean)
不起作用,如果 SomeBean 由 @Bean 注解组成。但如果 SomeBean 是 @Component
,它就可以工作。尽管调用了 @Bean=> SomeBean
方法并且创建了 bean 并将其添加到上下文中,但这甚至不起作用。尽管如此,@ConditionaOnBean
还是无法看到这个 bean(或者可能是使用 @Bean vs (@Component @Service @Respository @Service @Configuration)
创建的 bean 的顺序不同,并且在扫描完成后在应用程序上下文的末尾调用了 @Bean 注释方法)。
我看到了很多答案,几乎所有提到的 @Component
都是用于在扫描组件的位置自动装配,而 @Bean
完全声明该 bean 以不同的方式使用。让我展示一下它的不同之处。
@豆
首先,它是一个方法级别的注释。其次,您通常使用它在 Java 代码中配置 bean(如果您不使用 xml 配置),然后使用 ApplicationContext.getBean
方法从类中调用它。例子:
@Configuration
class MyConfiguration{
@Bean
public User getUser() {
return new User();
}
}
class User{
}
// Getting Bean
User user = applicationContext.getBean("getUser");
@零件
这是注释 bean 而非专用 bean 的一般方法。它是一个类级别的注释,用于通过 java 或 xml 配置避免所有配置内容。
我们得到这样的东西。
@Component
class User {
}
// to get Bean
@Autowired
User user;
而已。刚刚引入它是为了避免实例化和使用该 bean 的所有配置步骤。
@Bean
方法时,没有必要从 ApplicationContext 获取 User 对象。您仍然可以像使用 @Component
一样使用 @Autowire
来获取 bean。 @Bean
只是将 Bean 添加到 Spring Container 中,就像 @Component
所做的那样。区别如下。 1. 使用@Bean
,您可以将第三方类添加到 Spring Container。 2.使用@Bean
,您可以在运行时获得所需的接口实现(使用工厂设计模式)
Employee employeeImplA
选项 2 @Qulaifier("employeeImplA") Employee employee
的操作
您可以使用 @Bean
使现有的第三方类可用于您的 Spring 框架应用程序上下文。
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
通过使用 @Bean
注释,您可以将第三方类(它可能没有 @Component
并且可能不使用 Spring)包装为 Spring bean。然后,一旦使用 @Bean
包装它,它就会作为一个单例对象并在您的 Spring 框架应用程序上下文中可用。您现在可以使用依赖注入和 @Autowired
在您的应用程序中轻松共享/重用此 bean。
所以认为 @Bean
注释是第三方类的包装器/适配器。您想让第三方类可用于您的 Spring 框架应用程序上下文。
通过在上面的代码中使用 @Bean
,我显式声明了一个 bean,因为在方法内部,我使用 new
关键字显式创建了对象。我也在手动调用给定类的 setter 方法。所以我可以改变前缀字段的值。所以这个手工工作被称为显式创建。如果我将 @Component
用于同一个类,则在 Spring 容器中注册的 bean 将具有前缀字段的默认值。
另一方面,当我们用 @Component
注释一个类时,我们不需要手动使用 new
关键字。它由 Spring 自动处理。
当您使用 @Component
标记时,它与使用普通 bean 声明方法(使用 @Bean
注释)的 POJO(普通旧 Java 对象)相同。例如,下面的方法 1 和 2 将给出相同的结果。
方法一
@Component
public class SomeClass {
private int number;
public SomeClass(Integer theNumber){
this.number = theNumber.intValue();
}
public int getNumber(){
return this.number;
}
}
使用 'theNumber' 的 bean:
@Bean
Integer theNumber(){
return new Integer(3456);
}
方法二
//Note: no @Component tag
public class SomeClass {
private int number;
public SomeClass(Integer theNumber){
this.number = theNumber.intValue();
}
public int getNumber(){
return this.number;
}
}
两者都有豆子:
@Bean
Integer theNumber(){
return new Integer(3456);
}
@Bean
SomeClass someClass(Integer theNumber){
return new SomeClass(theNumber);
}
方法 2 允许您将 bean 声明放在一起,它更灵活等。您甚至可能想要添加另一个非香草 SomeClass bean,如下所示:
@Bean
SomeClass strawberryClass(){
return new SomeClass(new Integer(1));
}
您有两种生成 bean 的方法。一种是创建一个带有注释 @Component
的类。另一种是创建一个方法并用 @Bean
对其进行注释。对于那些包含带有 @Bean
的方法的类,应该用 @Configuration
进行注释一旦您运行您的 spring 项目,带有 @ComponentScan
注释的类将扫描每个带有 @Component
的类,并将此类的实例恢复为Ioc 容器。 @ComponentScan
会做的另一件事是运行带有 @Bean
的方法并将返回对象作为 bean 恢复到 Ioc 容器。因此,当您需要根据当前状态决定要创建哪种 bean 时,您需要使用 @Bean
。您可以编写逻辑并返回您想要的对象。另一件值得一提的是方法的名称,其中 @Bean
是 bean 的默认名称。
Bean和组件的区别:
https://i.stack.imgur.com/e8RlG.png
@component 及其特化(@Controller、@service、@repository)允许使用类路径扫描进行自动检测。如果我们看到像@Controller、@service、@repository 这样的组件类,Spring 框架会使用组件扫描自动扫描。
另一方面,@Bean 只能用于在配置类中显式声明单个 bean。
@Bean 用于显式声明单个 bean,而不是让 spring 自动执行。它从类定义中对 bean 进行分隔声明。
简而言之,@Controller、@service、@repository 用于自动检测,@Bean 用于从类中创建单独的 bean
- @Controller public class LoginController { --code-- } - @Configuration public class AppConfig { @Bean public SessionFactory sessionFactory() {--code-- }
创建 @Bean 是为了避免在编译时耦合 Spring 和您的业务规则。这意味着您可以在 PlayFramework 或 JEE 等其他框架中重用您的业务规则。
此外,您可以完全控制如何创建 bean,而默认 Spring 实例化是不够的。
我写了一篇文章谈论它。
https://coderstower.com/2019/04/23/factory-methods-decoupling-ioc-container-abstraction/
Spring 支持@Component、@Service、@Repository 等多种类型注解。所有这些都可以在 org.springframework.stereotype 包下找到。
@Bean 可以在 org.springframework.context.annotation 包下找到。
当我们的应用程序中的类使用上述任何注释进行注释时,然后在项目启动期间 spring 扫描(使用 @ComponentScan)每个类并将类的实例注入 IOC 容器。 @ComponentScan 会做的另一件事是运行带有 @Bean 的方法,并将返回对象作为 bean 恢复到 Ioc 容器。
@零件
如果我们用 @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,而不是像我们使用 @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
https://i.stack.imgur.com/zJpux.png
我希望澄清一些关于何时使用@Component 和何时使用@Bean 的问题。这可能有点令人困惑,但是当您开始编写更多应用程序时,它会变得非常自然。
<强> 1。关于@Component
@Component 的作用类似于@Configuration。
它们都表示注解的类有一个或多个bean 需要注册到Spring-IOC-Container
。
@Component 注解的类,我们称之为Component of Spring
。这是一个包含多个 bean 的概念。
Component class
需要由 Spring 自动扫描以注册 component class
的那些 bean。
<强> 2。关于@Bean
@Bean 用于注解component-class
的方法(如上所述)。表示注解方法返回的实例需要注册到Spring-IOC-Container
。
<强> 3。结论
两者的区别比较明显,用在different circumstances
中。一般用法是:
// @Configuration is implemented by @Component
@Configuration
public ComponentClass {
@Bean
public FirstBean FirstBeanMethod() {
return new FirstBean();
}
@Bean
public SecondBean SecondBeanMethod() {
return new SecondBean();
}
}
以上答案的附加点
假设我们有一个在多个应用程序中共享的模块,它包含一些服务。每个应用程序都不需要全部。
如果在这些服务类上使用 @Component 并在应用程序中扫描组件,
我们最终可能会检测到比必要更多的 bean
在这种情况下,您要么必须调整组件扫描的过滤,要么提供即使未使用的 bean 也可以运行的配置。否则,应用程序上下文将不会启动。
在这种情况下,最好使用 @Bean 注释并仅实例化那些 bean,
每个应用程序都需要这些
因此,本质上,使用 @Bean 将第三方类添加到上下文中。和 @Component 如果它只是在你的单个应用程序中。
不定期副业成功案例分享
@Component
继续类本身,而@Bean
继续类方法(产生类对象的实例)。what if you don't have the source codes
之前,我一直处于困境中?然后,卡布拉姆!当然,@Component
如果您拥有源代码,但如果您想将其他没有源代码的类组件化,那么@Bean
。我敢肯定还有其他的不同,但是女士们先生们,这很明确。@Bean
编辑的类?