Spring 中的 @Component 注解

您所在的位置:网站首页 若要删除一个文件应该使用哪个类的实例 Spring 中的 @Component 注解

Spring 中的 @Component 注解

2024-07-10 19:25| 来源: 网络整理| 查看: 265

1、概览

本文将带你全面了解 Spring @Component 注解及相关领域。

2、Spring ApplicationContext

在了解 @Component 之前,首先需要了解一下 Spring ApplicationContext。

Spring ApplicationContext 是 Spring 保存对象实例的地方,Spring 已确定这些实例将被自动管理和分发。这些实例被称为 Bean。

Spring 的一些主要功能包括 Bean 管理和依赖注入。

利用控制反转(Inversion of Control),Spring 可以从应用中收集 Bean 实例,并在适当的时候使用它们。可以在 Spring 中定义 Bean 依赖,而无需处理这些对象的设置和实例化。

使用 @Autowired 等注解将 Spring 管理的 Bean 注入应用的能力是在 Spring 中创建功能强大且可扩展代码的驱动力。

那么,如何让 Spring 来管理的 Bean 呢?可以利用 Spring 的自动 Bean 检测功能,通过在类中使用元注解(Stereotype Annotation)来实现。

3、@Component

@Component 是一个注解,它允许 Spring 自动检测自定义 Bean。

换句话说,无需编写任何明确的代码,Spring 就能做到:

扫描应用,查找注解为 @Component 的类 将它们实例化,并注入任何指定的依赖 在需要的地方注入

不过,大多数时候应该使用更专业的元(Stereotype)注解来实现这一功能。

3.1、Spring 元注解

Spring 提供了一些专门的元注解:@Controller、@Service 和 @Repository。它们都提供了与 @Component 相同的功能。

它们的作用都是一样的,因为它们都是由 @Component 作为元注解组成的注解。它们就像 @Component 别名,在 Spring 自动检测或依赖注入之外有专门的用途和意义。

理论上,如果愿意,可以只使用 @Component 来满足我们对 Bean 自动检测的需求。反过来,也可以编写使用 @Component 的专用注解。

不过,Spring 的其他领域会专门使用 Spring 的专用注解来提供额外的自动化优势。因此,应该在大多数情况下坚持使用预定义的专用注解。

假设在 Spring Boot 项目中拥有上述每种情况的示例:

@Controller public class ControllerExample { } @Service public class ServiceExample { } @Repository public class RepositoryExample { } @Component public class ComponentExample { } @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Component public @interface CustomComponent { } @CustomComponent public class CustomComponentExample { }

可以编写一个测试,证明 Spring 能自动检测到每个 Bean 并将其添加到 ApplicationContext 中:

@SpringBootTest @ExtendWith(SpringExtension.class) public class ComponentUnitTest { @Autowired private ApplicationContext applicationContext; @Test public void givenInScopeComponents_whenSearchingInApplicationContext_thenFindThem() { assertNotNull(applicationContext.getBean(ControllerExample.class)); assertNotNull(applicationContext.getBean(ServiceExample.class)); assertNotNull(applicationContext.getBean(RepositoryExample.class)); assertNotNull(applicationContext.getBean(ComponentExample.class)); assertNotNull(applicationContext.getBean(CustomComponentExample.class)); } } 3.2、@ComponentScan

@Component 只是一个普通的注解。该注解的作用是将 Bean 与其他对象(如 Domain 对象)区分开来。

Spring 使用 @ComponentScan 注解将它们收集到 ApplicationContext 中。

Spring Boot 中的 @SpringBootApplication 注解就是一个包含了 @ComponentScan 的注解。只要 @SpringBootApplication 类位于项目根目录,它就会默认扫描应用中定义的每个 @Component。

如果 @SpringBootApplication 类不在项目根目录下,或者想扫描外部资源,可以显式配置 @ComponentScan 来查找指定的任何包,只要它存在于 classpath 上。

定义一个超出扫描范围的 @Component Bean:

package com.baeldung.component.scannedscope; @Component public class ScannedScopeExample { }

接着,通过 @ComponentScan 注解指定其所在的包:

package com.baeldung.component.inscope; @SpringBootApplication @ComponentScan({"com.baeldung.component.inscope", "com.baeldung.component.scannedscope"}) public class ComponentApplication { //public static void main(String[] args) {...} }

最后,可以测试一下它是别成功扫描加载到:

@Test public void givenScannedScopeComponent_whenSearchingInApplicationContext_thenFindIt() { assertNotNull(applicationContext.getBean(ScannedScopeExample.class)); }

当要扫描项目中的外部依赖时,这种情况更有可能发生。

3.3、@Component 的限制

在某些情况下,无法使用 @Component。但仍希望指定对象成为 Spring 管理的 Bean。

在项目外的包中定义一个使用 @Component 注解的对象:

package com.baeldung.component.outsidescope; @Component public class OutsideScopeExample { }

下面的测试可以证明 ApplicationContext 不包含外部包中定义的组件:

@Test public void givenOutsideScopeComponent_whenSearchingInApplicationContext_thenFail() { assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(OutsideScopeExample.class)); }

另外,因为它来自第三方,可能无法编辑源码,无法添加 @Component 注解。又或者,我们想根据运行环境有条件地使用一种 Bean 实现,而不是另一种。自动检测通常就足够了,但当它无法满足需求时,可以使用 @Bean 注解。

4、@Component 和 @Bean

@Bean 也是 Spring 用于在运行时收集 Bean 的注解,但它不是用在类级别上的。相反,使用 @Bean 注解方法,以便 Spring 可以将方法的结果存储为 Spring Bean。

首先,创建一个没有注解的 POJO:

public class BeanExample { }

在 @Configuration 注解的配置类中,可以创建一个生成 Bean 的方法:

@Bean public BeanExample beanExample() { return new BeanExample(); }

BeanExample 可能代表一个本地类,也可能是一个外部类。这并不重要,只需要返回它的一个实例即可。

然后,编写一个测试,验证 Spring 是否加载了 Bean:

@Test public void givenBeanComponents_whenSearchingInApplicationContext_thenFindThem() { assertNotNull(applicationContext.getBean(BeanExample.class)); }

由于 @Component 和 @Bean 之间的差异,应该注意一些重要的影响。

@Component 是一个类级别的注解,而 @Bean 是方法级别的注解,因此只有在类的源代码可编辑时,才可以使用 @Component 作为选项。@Bean 始终可以使用,但它的语法更加冗长。 @Component 与 Spring 的自动检测兼容,但 @Bean 需要手动实例化类。 使用 @Bean 可以将 Bean 的实例化与其类定义分离。因此,可以使用它将第三方类转化为 Spring Bean。这也意味着可以添加逻辑来决定要使用哪个实例作为 Bean。 5、总结

本文介绍了 Spring @Component 注解和其他相关主题。

各种 Spring 元注解,只是 @Component 的专门版本。

@Component 注解的组件依需要被 @ComponentScan 扫描才能被实例化为 Spring Bean。

如果不能编辑源码,没法给组件类添加 @Component 注解,那么可以自定义配置类,在方法上使用 @Bean 注解手动地初始化组件类为 Spring Bean。

Ref:https://www.baeldung.com/spring-component-annotation



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3