SpringBoot原理
起步依赖
依赖传递,a依赖b,b依赖c
自动配置
Springboot的自动配置就是当Spring容器启动后,一些配置类、bean对象就自动存入到了IOC容器中,不用手动配置了
Springboot采用的是@EnableXXXX注解,分装了@Import注解,导入对应的类
自动配置原理是Spring Boot的核心功能之一,它可以根据项目中的配置文件、类路径、环境变量等条件,自动地配置应用程序。通过自动配置,开发人员可以专注于编写业务逻辑,而无需花费时间在繁琐的配置工作中。
面试回答
@SpringBootApplication 是一个复合注解,真正实现自动装配的注解是@EnableAutoConfiguration。
自动装配的实现主要依靠三个核心关键技术:
1.引入 Starter 启动依赖组件的时候,这个组件里面必须要包含@Configuration 配置类,在这个配置类里面通过@Bean 注解声明需要装配到 IOC 容器的 Bean 对象。
2.这个配置类是放在第三方的 jar 包里面,然后通过 SpringBoot 中的约定优于配置思想,把这个配置类的全路径放在 classpath:/META-INF/spring.factories 文件
中。这样 SpringBoot 就可以知道第三方 jar 包里面的配置类的位置,这个步骤主要是用到了 Spring 里面的 SpringFactoriesLoader 来完成的。
3.SpringBoot 拿到所第三方 jar 包里面声明的配置类以后,再通过 Spring 提供的ImportSelector 接口,实现对这些配置类的动态加载。
询问Chatgpt回答
Springboot自动装配原理理解是不是:
两个部分第一个动态加载配置类使用@Import将类加载到IOC容器中,第二个是扫描类路径下的所有配置类,通过SPI技术将Meta—INF中的配置文件中的类路径加载到IOC容器中
回答
Spring Boot的自动装配机制确实可以理解为两个主要部分,其中包括使用 @Import 注解和基于 SPI(Service Provider Interface)的配置文件加载。
@Import 注解: Spring Boot通过 @Import 注解来实现动态加载配置类。@Import 注解用于引入其他配置类,将其加载到当前配置类的上下文中。这样,你可以在一个配置类中引入其他配置类,形成一个配置类的链条,最终构建整个应用程序的配置。这种方式使得配置的模块化和复用更加方便。
@Configuration
@Import({DatabaseConfig.class, SecurityConfig.class})
public class AppConfig {
// ...
}
SPI 技术和元数据文件: Spring Boot通过扫描类路径下的 META-INF/spring.factories 文件来实现自动装配。在这个文件中,可以配置各种组件的实现类,Spring Boot 在启动时会扫描这些配置文件,然后将对应的类加载到 IOC 容器中。这就是 SPI(Service Provider Interface)的基本思想,通过配置文件声明服务的提供者,然后在运行时动态加载这些提供者。
例如,如果你在类路径下的 META-INF/spring.factories 文件中声明了一个自定义的 MyService 接口的实现类:
org.example.MyService=org.example.MyServiceImpl
Spring Boot 在启动时会扫描这个配置文件,将 MyServiceImpl 加载到 IOC 容器中。
总体来说,Spring Boot 的自动装配机制是通过这两种方式相结合实现的。通过 @Import 注解引入配置类,通过扫描类路径下的元数据文件加载具体的实现类,Spring Boot 构建了一个灵活且可扩展的自动装配机制,使得开发者可以更方便地进行配置和扩展。
基础知识复习:SPI源码
https://github.com/cmdch2017/Bean_IOC.git
public interface IShout {
void shout();
}
public class Cat implements IShout {
@Override
public void shout() {
System.out.println("miao miao");
}
}
public class Dog implements IShout {
@Override
public void shout() {
System.out.println("wang wang");
}
}
resources下META-INF代码
对比,不用SPI技术
public class Main {
public static void main(String[] args) {
List<IShout> shouters = new ArrayList<>();
shouters.add(new Cat());
shouters.add(new Dog());
for (IShout s : shouters) {
s.shout();
}
}
}
用SPI技术
public class SPIMain {
public static void main(String[] args) {
ServiceLoader<IShout> shouts = ServiceLoader.load(IShout.class);
for (IShout s : shouts) {
s.shout();
}
}
}