1.概述
在本教程中,我们将全面介绍Spring @Component
批注和相关区域。到最后,我们将看到使用它与某些Spring核心功能集成的不同方法,以及如何利用其许多优点。
2. Spring ApplicationContext
在我们了解@Component
的值之前,我们必须首先了解一些有关Spring ApplicationContext
。在这里,Spring会保存已确定要自动管理和分发的对象的实例。这些被称为豆。 Bean管理和依赖注入的机会是Spring的一些主要功能。
使用“控制反转”原理, Spring从我们的应用程序中收集bean实例,并在适当的时间使用它们。我们可以显示对Spring的bean依赖关系,而无需处理那些对象的设置和实例化。
使用@Autowired
注释将Spring托管的bean注入我们的应用程序的能力是在Spring中创建功能强大且可伸缩的代码的驱动力。
那么,我们如何告诉Spring我们希望它为我们管理的bean?我们应该通过在类上使用构造型注释来利用Spring的自动bean检测功能。
3. @Component
@Component
是一个注释,它允许Spring自动检测我们的自定义bean。
换句话说,无需编写任何显式代码,Spring即可:
- 扫描我们的应用程序以查找带有
@Component
- 实例化它们并将任何指定的依赖项注入到它们中
- 随时随地注入
但是,大多数开发人员更喜欢使用更专业的构造型注释来实现此功能。
3.1。Spring 其他注解
Spring提供了一些专门的@Controller
, @Service
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会自动检测到每个测试并将其添加到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与其他对象(例如域对象)区分开的目的。但是, Spring使用@ComponentScan
批注将它们全部收集到其ApplicationContext
。
如果我们正在编写Spring Boot应用程序,那么了解@SpringBootApplication
是一个包含@ComponentScan
的组合批注会很有帮助。只要我们的@SpringBootApplication
类位于项目的根目录下,它将扫描默认情况下定义的@Component
但是,如果我们的@SpringBootApplication
类不能位于项目的根目录下,或者我们想扫描外部源,则可以@ComponentScan
以查找我们指定的任何包,只要它存在于类路径中即可。
让我们定义一个范围外的@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 givenBeanComponent_whenSearchingInApplicationContext_thenFindIt() {
assertNotNull(applicationContext.getBean(BeanExample.class));
}
@Component
和@Bean
之间的差异,我们应该注意一些重要的含义。
-
@Component
是类级别的注释,但是@Bean
是方法级别的,因此@Component
仅在类的源代码可编辑时才是一个选项。@Bean
总是可以使用,但是更冗长。 -
@Component
与Spring的自动检测兼容,但是@Bean
需要手动的类实例化。 - 使用
@Bean
将Bean的实例与其类定义解耦。这就是为什么我们可以使用它甚至将3rd Party类制作为Spring Bean的原因。这也意味着我们可以引入逻辑来决定要使用bean的几个可能的实例选项中的哪一个。
5.结论
我们刚刚探讨了Spring @Component
批注以及其他相关主题。首先,我们讨论了各种Spring构造型注解,它们只是@Component
专门版本。然后,我们了解到@Component
不会执行任何操作,除非@ComponentScan
可以找到它。最后,由于无法@Component
上使用@Component,因此我们学习了如何使用@Bean
注解。
0 评论