Spring Boot 对Bean扫描的几种方式
在Spring框架中,Bean是构成应用程序的基石,它们是被Spring容器管理的对象。Spring Boot作为Spring的一个子项目,继承了Spring的依赖注入特性,并且进一步简化了配置。在Spring Boot中,Bean的扫描是自动配置的关键部分。本文将详细介绍Spring Boot中Bean扫描的几种方式,并提供代码示例。
1. Spring中Bean扫描方式回顾
在传统的Spring项目中,我们可以通过两种方式指定Bean的扫描路径:
1.1 XML配置文件方式
在XML配置文件中,使用<context:component-scan>
标签来指定要扫描的包路径。例如:
xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.example.demo"/>
</beans>
上述代码中,base-package
属性指定了要扫描的包路径为com.example.demo
及其子包,Spring会在这些包中查找被注解标识为Bean的类,并将其注册到Spring容器中。
1.2 配置类方式
使用配置类时,借助@ComponentScan
注解来指定扫描包路径。示例如下:
java
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.example.demo")
public class AppConfig {
}
2. Spring Boot中Bean扫描原理
2.1 启动类注解的作用
在Spring Boot中,@SpringBootApplication
注解是启动类的关键,它是一个组合注解,包含了@Configuration
、@EnableAutoConfiguration
和@ComponentScan
。
java
package com.baeldung.componentscan.springbootapp;
// ...
@SpringBootApplication
public class SpringBootComponentScanApp {
private static ApplicationContext applicationContext;
@Bean
public ExampleBean exampleBean() {
return new ExampleBean();
}
public static void main(String[] args) {
applicationContext = SpringApplication.run(SpringBootComponentScanApp.class, args);
checkBeansPresence(
"cat", "dog", "rose", "exampleBean", "springBootComponentScanApp");
}
private static void checkBeansPresence(String... beans) {
for (String beanName : beans) {
System.out.println("Is " + beanName + " in ApplicationContext: " +
applicationContext.containsBean(beanName));
}
}
}
2.2 默认扫描范围
Spring Boot默认会扫描启动类所在包以及其子包中的Bean。
2.3 演示默认扫描范围问题
如果我们有一个结构如下的项目:
markdown
com.baeldung.componentscan.springbootapp
├── SpringBootComponentScanApp.java
├── animals
│ ├── Cat.java
│ └── Dog.java
└── flowers
└── Rose.java
Spring Boot会扫描com.baeldung.componentscan.springbootapp
包及其子包中的所有Bean。
2.4 指定扫描其他包的方法
如果需要指定扫描其他包,可以在@SpringBootApplication
注解中使用@ComponentScan
。
java
@SpringBootApplication
@ComponentScan(basePackages = "com.baeldung.componentscan.springbootapp.animals")
public class SpringBootComponentScanApp {
// ...
}
这样,Spring Boot只会扫描com.baeldung.componentscan.springbootapp.animals
包中的Bean。
3. @ComponentScan
With Arguments
3.1 @ComponentScan
for Specific Packages
我们可以改变基础包:
java
@ComponentScan(basePackages = "com.baeldung.componentscan.springapp.animals")
@Configuration
public class SpringComponentScanApp {
// ...
}
现在输出将只包含com.baeldung.componentscan.springapp.animals
包中的Bean。
3.2 @ComponentScan
with Multiple Packages
Spring提供了一种方便的方式来指定多个包名。可以使用字符串数组:
java
@ComponentScan(basePackages = {"com.baeldung.componentscan.springapp.animals", "com.baeldung.componentscan.springapp.flowers"})
或者,从Spring 4.1.1开始,可以使用逗号、分号或空格来分隔包列表:
java
@ComponentScan(basePackages = "com.baeldung.componentscan.springapp.animals;com.baeldung.componentscan.springapp.flowers")
@ComponentScan(basePackages = "com.baeldung.componentscan.springapp.animals,com.baeldung.componentscan.springapp.flowers")
@ComponentScan(basePackages = "com.baeldung.componentscan.springapp.animals com.baeldung.componentscan.springapp.flowers")
4. 总结
Spring Boot通过简化配置,使得Bean的扫描变得更加容易。通过@SpringBootApplication
注解,Spring Boot自动扫描启动类所在包及其子包中的Bean。如果需要自定义扫描路径,可以使用@ComponentScan
注解来指定。这些机制使得Spring Boot在微服务架构中非常受欢迎,因为它大大减少了配置的复杂性。