当我们启动Spring项目的时候,就会初始化Spring的容器,Spring就会扫描启动引导类所在包及其子包中类的注解,并调用这些加了注解的类的构造方法创建对象(控制翻转),再创建了这些类的对象之后,就会找使用了@Autowired注解的地方进行赋值(依赖注入)。随后就会将创建的对象初始化(init)。最后Spring容器销毁的时候,创建的对象也会销毁(destroy)。
总结:
1、调用这些加了注解的类的构造方法创建对象(控制翻转)
2、找使用了@Autowired注解的地方进行赋值(依赖注入)
3、将创建的对象初始化(init)
4、将创建的对象销毁。
当断点停留在SpringApplication.run方法时,也就是还没有初始化容器时,此时Spring并没有创建相关对象(因为此时Spirng的容器还没有初始化)。
将断点放行,可以在控制台发现实例A的生命周期和"一"中的总结是一样的。
定义class A,和1.1中的一模一样,在class A中的set方法中依赖注入B
定义class B,在class B中的set方法中依赖注入A。
此时就会出现循环依赖的问题:
因为我们从"一"中得知Bean的生命周期的流程大概是:
1、创建对象
2、依赖注入,其中就包括set方法依赖注入。
3、初始化
假如Spring首先创建了对象A,然后调用A类中的set方法对方法参数b进行依赖注入赋值, 此时就要在容器中去找对象B,而此时可能对象B还没有创建成功,所以就出现了循环依赖的问题。
在springboot2.6.0之前自动解决,无需任何配置。
在springboot2.6.0之后的版本中需要在配置文件中开启运行set方式循环依赖
spring.main.allow-circular-references=true
构造方式循环依赖的原因和2.1中set方式循环依赖的原因差不多,不在过多介绍,下面进行代码的演示。
C中的构造方法依赖注入D
D中的构造方法依赖注入C
如果构造方法中只有一个方法参数,可以省略 @Autowired,所以上面的C、D中的构造方法里面并没有使用@Autowired,注解。
在其中一个类的构造方法中,加上@Lazy注解即可。
在C的构造方法中使用@Lazy注解,表示创建D的代理对象而不是真实对象进行注入。
使用lombok工具包首先需要在pom.xml配置文件中导入lombok的相关依赖
org.projectlombok
lombok
以下注解在pom.xml配置文件中导入了lombok工具包的相关依赖后即可使用。
@Data注解可以生成上图中的所有方法,除了有参构造方法。
在Bean上使用@Slf4j注解,就可以使用log对象进行日志输出。
其实我们创建的SpringBoot工程已经整合了Junit单元测试,并且使用的是Junit5的版本,好处是测试方法不需要使用public修饰。
测试类上的@SpringBootTest注解表示该类是一个SpringBoot单元测试类,在该测试类中可以直接使用@Autowired注解注入要使用对象