wordpress 快站浏览器小游戏在线玩
文章目录
- 什么是 SpringBoot 自动配置
- Spring 加载 Bean
- 问题描述
- 原因分析
- 解决方案
- @ComponentScan
- @Import
- 1 . 导入类
- 2 . 导入 ImportSelector 接口实现类
- 问题
什么是 SpringBoot 自动配置
SpringBoot 的自动配置就是当 Spring 容器启动之后,一些配置类,bean 对象就自动存入到了 IoC 容器中,不需要我们手动去声明,从而简化了开发,省去了繁琐的配置操作
SpringBoot 自动配置,就是指 SpringBoot 是如何将依赖 jar 包中的配置以及 Bean 加载到 Spring IoC 容器中的
我们学习主要分以下两个方面:
Spring是如何把对象加载到SpringIoC容器中的SpringBoot是如何实现的
Spring 加载 Bean
问题描述
需求:使用 Spring 管理第三方的 jar 包的配置
- 引入第三方的包,其实就是在该项目下,引入第三方的代码,我们采用在该项目下创建不同的目录来模拟第三方的代码引入
数据准备:
- 创建项目
spring-autoconfig,当前项目目录为:com.example.demo - 模拟第三方代码文件在
com.bite.autoconfig目录下
第三方文件代码:
public class BiteConfig { public void study() { System.out.println("start study..."); }
}
- 获取
BiteConfig这个Bean
写测试代码
@SpringBootTest
class ApplicationTests { @Autowired private ApplicationContext applicationContext; @Test void contextLoads() { BiteConfig biteConfig = applicationContext.getBean(BiteConfig.class, "biteConfig"); System.out.println(biteConfig); }
}
- 运行程序

- 观察日志:
No qualifying bean of type 'com.bite.autoconfig.BiteConfig' available - 没有
com.bite.autoconfig.BiteConfig这个类型的Bean
原因分析
Spring 通过五大注解和 @Bean 注解可以帮助我们把 Bean 加载到 SpringIoC 容器中,以上有个前提就是这些注解类需要和 SpringBoot 启动类在同一个目录下(@SpringBootApplication 标注的类就是 SpringBoot 的启动类)
- 启动类所在目录为:
com.example.deml,而BiteConfig这个类在com.bite.autoconfig下,所以SpringBoot没有扫描到
解决方案
我们需要指定路径或者引入的文件,告诉 spring,让 Spring 进行扫描到
常见的解决方案有两种:
@ComponentScan组件扫描Import导入(使用@Import导入的类会被Spring加载到IoC容器中)
我们通过代码来看如何解决
@ComponentScan
通过 @ComponentScan 注解,指定 Spring 扫描路径
@ComponentScan("com.bite.autoconfig")
@SpringBootApplication
public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
- 可以指定扫描多个包
@ComponentScan({"com.bite.autoconfig","com.example.demo"})
运行程序:
可以看到,这次 biteConfig 的 Bean 获取到了
Spring是否使用了这种方式呢?- 非常明显,没有(因为我们引入第三方框架时,没有加扫描路径,如
mybatis) - 如果
SpringBoot采用这种方式,当我们引入大量的第三方依赖,比如MyBatis,jackson等时,就需要在启动类上配置不同依赖需要扫描的包 - 这种方式会非常繁琐
@Import
@Import 导入主要有以下几种形式
- 导入类
- 导入
ImportSelector接口实现类
1 . 导入类
@Import(BiteConfig.class)
@SpringBootApplication
public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
- 运行程序

- 可以看到,这种方式也可以告诉
Spring加载biteConfig
问题:如果又多了一些配置项呢?
@Component
public class BiteConfig2 { public void study2() { System.out.println("start study2..."); }
}
我们可以采用导入多个类
@Import({BiteConfig.class, BiteConfig2.class})
@SpringBootApplication
public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
很明显,这种方式也很繁琐,所以,SpringBoot 依然没有采用
2 . 导入 ImportSelector 接口实现类
ImportSelector 接口实现类
public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { // 需要导入的全限定类名 return new String[]{"com.bite.autoconfig.BiteConfig", "com.bite.autoconfig.BiteConfig2"}; }
}
启动类:
@Import(MyImportSelector.class)
@SpringBootApplication
public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
运行程序:
- 可以看到,我们采用这种方式也可以导入第三方依赖提供的
Bean
问题
问题:
但是他们都有一个明显的问题,就是使用者需要知道第三方依赖中有哪些 Bean 对象或配置类。如果漏掉了其中一些 Bean,就可能导致我们的项目出现大事故
依赖中有哪些 Bean,使用时需要配置哪些 Bean,第三方依赖最清楚,那能否由典发那个依赖来做这件事呢?
- 比较常见的方案就是第三方依赖给我们提供一个注解,这个注解一般都以
@EnableXxxx开头,注解中封装的就是@Import注解
- 第三方依赖提供注解
import org.springframework.context.annotation.Import; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(MyImportSelector.class)
public @interface EnableBiteConfig {
}
注解中封装 @Import 注解,导入 MyImportSelector.class
- 在启动类上使用第三方提供的注解
@EnableBiteConfig
@SpringBootApplication
public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
运行程序:
- 可以看到,这种方式也可以导入第三方依赖提供的
Bean - 并且这种方式更优雅一点,
SpringBoot采用的也是这种方式
