当前位置: 首页 > article >正文

Spring的常用注解之@Component——day1

1、@Component

@Component:泛指各种组件;它允许 Spring 自动检测自定义 Bean。换句话说,无需编写任何明确的代码,Spring 就能做到:

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

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

2、Spring元注解

Spring 提供了一些专门的元注解:@Controller@Service 和 @Repository。它们都提供了与 @Component 相同的功能。都可以称为@Component。它们的作用都是一样的,因为它们都是由 @Component 作为元注解组成的注解。它们就像 @Component 别名,在 Spring 自动检测或依赖注入之外有专门的用途和意义。理论上,如果愿意,可以只使用 @Component 来满足我们对 Bean 自动检测的需求。反过来,也可以编写使用 @Component 的专用注解。

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

@Controller:控制层

@Service:业务层

@Repository:数据访问层

假设在 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、@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));
}

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

4、@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 注解。

5、@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。

6、总结

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

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

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

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

 

转载自:https://springdoc.cn/spring-component-annotation/


http://www.kler.cn/a/379545.html

相关文章:

  • 与IP网络规划相关的知识点
  • 桥接IC lt7911d linux 驱动
  • 使用 SSH 蜜罐提升安全性和记录攻击活动
  • 智能交易模型的探索与发展
  • AI打造超写实虚拟人物:是科技奇迹还是伦理挑战?
  • P11233 [CSP-S 2024] 染色 题解
  • 【Keyframes】Deep Convolutional Pooling Transformer for Deepfake Detection
  • 【VMware】使用笔记
  • STL:标准模板库
  • Ubuntu 22.4 LTS 源码编译Tigervnc
  • 【P2-9】ESP8266 WIFI模块在STA模式下作为TCP客户端上电自动进入透传数据模式
  • javaNIO核心知识.中
  • 苍穹外卖Day3test报错javax.websocket.server.ServerContainer not available
  • Qt 实战(10)模型视图 | 10.7、自定义 QTableWidget
  • 关于最新create-react-app使用react-app-rewired2.x添加webpack配置
  • [CISCN 2021初赛]robot
  • 传统的自然语言处理评估指标
  • GPU 服务器:高性能计算的核心驱动力
  • Web Broker(Web服务应用程序)入门教程(2)
  • LeetCode 3259.超级饮料的最大化能力(动态规划状态机模型入门)
  • 探索数据管理新境界:PyTables库的奥秘
  • 低代码信息中心:赋能创新的未来
  • 密码学是如何保护数据传输的安全性?
  • 计算机网络 -- HTTP 协议详解
  • PyTorch实战-手写数字识别-MLP模型
  • Redis高级篇之缓存一致性详细教程