目录
核心注解
SpringBoot的启动类有一个核心注解:@SpringBootApplication,这个注解包含下面三个注解:
1.@SpringBootConfiguration:标明这是一个配置类,和普通的@Configuration功能一样;
2. @EnableAutoConfiguration:启用Spring Boot的自动配置机制。该注解告诉Spring Boot根据应用的依赖和配置来自动配置应用的各个组件。通过@EnableAutoConfiguration注解,Spring Boot可以根据classpath中的jar包、配置文件等信息来自动配置应用;
3. @ComponentScan:启用组件扫描机制。该注解告诉Spring Boot在指定的包及其子包中扫描并注册所有被@Component注解标识的类。被@ComponentScan注解标识的类将会被自动实例化,并可以通过@Autowired注解进行依赖注入;
Bean的生命周期
主要分为下面八步,见图知义。
补充说一下:
1、XML文件中Bean的相关信息会打包成一个BeanDefinition对象供框架读取;
2、如果实现了Aware接口,那么就会在初始化之前执行那几个Aware后缀的方法(需重写);
3、前、后置处理器是基于AOP实现的;
4、初始化方法可以通过实现InitializingBean接口实现;
5、实例化是创建对象的过程,构造是在实例化过程中执行构造函数的过程。构造函数是一种特殊的方法,用于初始化对象的状态和成员变量。初始化是在对象创建完成后对对象进行赋初值或执行额外操作的过程,可以在构造函数中完成。
IOC/DI
IoC(Inversion of Control)和DI(Dependency Injection)是Spring框架的核心原理。
IoC是一种设计思想,它将对象的创建、依赖关系的管理和对象的生命周期等任务交给容器来完成,而不是由开发者手动管理。在传统的编程模式中,开发者需要自己创建对象并处理对象之间的依赖关系,而在IoC模式下,容器负责管理对象的创建和依赖关系。
DI是IoC的一种实现方式,它通过依赖注入的方式来实现对象之间的解耦。依赖注入是指容器在创建对象时,自动将依赖的对象注入到目标对象中,而不需要开发者手动去获取依赖对象。通过依赖注入,对象之间的依赖关系被解耦,使得代码更加灵活、可测试和可维护。
在Spring框架中,IoC和DI的实现是通过ApplicationContext来完成的。ApplicationContext是Spring的核心容器,它负责管理Bean的生命周期和依赖关系。当应用程序启动时,ApplicationContext会根据配置信息和注解扫描机制,自动创建并初始化Bean,并将它们注册到容器中。
在进行依赖注入时,Spring容器会通过反射机制实例化Bean,并自动解析和注入依赖的对象。开发者可以通过在目标类的构造方法、Setter方法或字段上使用@Autowired或@Inject等注解来标识依赖关系,Spring容器会根据这些注解来自动注入对应的依赖对象。
注入IOC容器
在Spring Boot中,使用了@ComponentScan注解来指定需要扫描的包路径,从而扫描并注册带有@Component及其派生注解(如@Controller、@Service等)的类到IOC容器中。这样,在其他地方可以通过@Autowired或@Inject等注解来注入这些Bean,实现依赖注入的功能。
需要注意的是,这些注解并不属于条件注解,它们不会根据特定的条件来决定是否启用自动配置。它们只是用于标识和管理Bean的作用域和功能。而条件注解是用于控制自动配置的启用和禁用的。
ApplicationContext
ApplicationContext容器是IoC容器的一种具体实现。
ApplicationContext是Spring框架的核心容器,负责管理Bean的生命周期和依赖关系。它是对IoC原则的具体实现,通过自动化配置和依赖注入等机制,实现了对象的解耦和灵活组装。
与传统的IoC容器相比,ApplicationContext具有以下特点:
1. 完善的功能:ApplicationContext提供了丰富的功能,如依赖注入、生命周期管理、配置和资源管理、事件机制、AOP支持等。它不仅仅是一个简单的对象容器,还提供了一系列高级功能来支持应用程序的开发和运行。
2. 多样的配置方式:ApplicationContext支持多种配置方式,包括XML配置、注解配置和Java配置等。开发者可以根据自己的喜好和需求选择合适的配置方式。
3. 容器的启动和关闭:ApplicationContext在应用程序启动时会自动加载和初始化Bean,并在应用程序关闭时销毁Bean。它负责管理整个应用程序的生命周期。
4. 容器的上下文环境:ApplicationContext提供了一个上下文环境,可以通过它来获取配置文件中的属性值、加载外部资源、进行国际化等操作。
容器的一种具体实现。它是Spring框架的核心容器,负责管理Bean的生命周期和依赖关系,并提供了丰富的功能和灵活的配置方式。通过使用ApplicationContext,开发者可以更加方便地管理和组织应用程序的组件和依赖关系。
自动配置
Spring Boot自动配置的原理是基于条件注解和Spring的SPI(Service Provider Interface)机制实现的。
首先,Spring Boot会扫描classpath下的META-INF/spring.factories文件,该文件中列出了所有自动配置类的全限定名。Spring Boot会根据这些自动配置类的条件注解来判断是否需要自动配置。
条件注解是Spring Boot自动配置的核心,它可以根据一定的条件来决定是否启用自动配置。常见的条件注解有:
- @ConditionalOnClass:当指定的类存在于classpath中时,才会启用自动配置。
- @ConditionalOnBean:当指定的Bean存在于ApplicationContext中时,才会启用自动配置。
- @ConditionalOnProperty:当指定的配置属性存在并且值满足条件时,才会启用自动配置。
- @ConditionalOnMissingBean:当指定的Bean不存在于ApplicationContext中时,才会启用自动配置。
根据条件注解的判断结果,Spring Boot会决定是否启用自动配置。如果启用了自动配置,Spring Boot会自动将相关的Bean注册到ApplicationContext中,完成自动配置的过程。
此外,Spring Boot还提供了一些注解和配置类,用于自定义和扩展自动配置。例如,可以使用@EnableAutoConfiguration注解来启用自动配置,也可以通过@ConfigurationProperties注解来自定义配置属性。
循环依赖
循环依赖有三种情况:1、A依赖A本身;2、A依赖B,B依赖C;3、A依赖B,B依赖C,C依赖B;
Spring有三个容器分别存放一、二、三级缓存。
一级缓存是初始化好的Bean,无法解决循环依赖问题
二级缓存是已经实例化,但是没有初始化的Bean,可以初步解决循环依赖的问题,但是如果A是代理对象,仍然无法解决。
Spring的二级缓存无法解决代理对象的问题是因为代理对象的创建需要在Bean的初始化阶段进行,而二级缓存是在Bean的实例化阶段进行的,为此引入了三级缓存。
如果A是代理对象,那么singletonFactories中存的就是代理对象;如果是元对象,那么singltnFactories存的就是元对象。
二级缓存和三级缓存的区别在于缓存的级别和存储的内容不同。二级缓存是在ApplicationContext级别进行缓存,存储的是Bean实例;而三级缓存是在BeanFactory级别进行缓存,存储的是Bean的原始定义。此外,二级缓存是每个ApplicationContext实例独立的,而三级缓存是整个BeanFactory共享的。
构造方法出现了循环依赖怎么解决?
在解决循环依赖时,Spring会先创建一个未完全初始化的Bean实例,并将其放入一级缓存中。然后继续创建依赖的Bean,待所有相关Bean都创建完成后,再完成Bean的初始化过程。在这个过程中,虽然会生成Bean的原始定义,但由于循环依赖的存在,无法将完整的Bean放入三级缓存中。
因此,构造方法出现循环依赖会导致无法生成完整的Bean实例,从而无法将其放入三级缓存中。Spring通过"提前暴露"的方式来解决循环依赖,而不是依赖于缓存来提供Bean的实例。