1. Spring 依赖注入
Bean 对象与普通对象的区别:Bean 对象是由Spring 创建的,Spring 用无参的构造方法创建对象,那么所得到的对象属性应该是没有值的,但是最后生成的 Bean 对象的属性是有值的,这个过程中间,就发生了依赖注入。
class文件 ---> 构造方法 ---> 对象 --->依赖注入 ---> 其他步骤---> Bean对象
依赖注入就是给加了@Autowired 注解的属性赋值
2. 单例池
单例 Bean 每次创建得到的结果,都是同一个对象,它的底层是用一个Map(单例池),每一次获取对象,都是从Map 获取,如果没有对象,则执行创建流程,并把对象放到Map 中; 放到单例池中的对象,就认为是一个Bean对象
3. @PostConstruct 底层原理
在初始化前需要执行的一些步骤,可以用@PostConstruct 注解标识, Spring 会判断创建的对象中,有哪些方法是加了 @PostConstruct 注解的
class文件 ---> 构造方法 ---> 对象 --->依赖注入 ---> 初始化前(@PostConstruct)---> 初始化 ---> 初始化后 ---> ---> Bean对象
4. 初始化
Bean 可以实现 InitializingBean 接口,在这个接口里有一个 afterPropertiesSet() 方法, 在Spring 对象初始化的时候,会执行 afterPropertiesSet() 方法;
Spring 会判断 对象是否实现 InitializingBean 接口, 如果实现了,就会把对象强制转换成 InitializingBean 对象,去执行 afterPropertiesSet() 方法,这样就可以间接执行到对象的 afterPropertiesSet() 方法
class文件 ---> 构造方法 ---> 对象 --->依赖注入 ---> 初始化前(@PostConstruct)---> 初始化(afterPropertiesSet() 方法) ---> 初始化后 --->单例池 ---> Bean对象
5. 初始化后(AOP)
如果spring 对象有AOP,那么就会产生代理对象,把代理对象放到单例池中
class文件 ---> 构造方法 ---> 对象 --->依赖注入 ---> 初始化前(@PostConstruct)---> 初始化(afterPropertiesSet() 方法) ---> 初始化后(AOP) ---> 单例池 ---> Bean对象
6. 推断构造方法
如果 Bean 对象只有一个有参构造方法,那么属性其实是有值的;
那么为什么 OrderService 没有加 @Autowired 注解还会有值?Spring 在构造UserService 这个 Bean 时,发现只有一个构造方法,所以会使用该构造方法;
有多个构造方法的情况下,如果有无参的构造方法,那么就用无参的;
如果没有无参构造方法的话就会报错,这时候可以给其中一个构造方法加上 @AutoWired 注解,Spring就会使用这个构造方法;
7. 单例Bean的一些解释
单例 Bean 是指 Bean的名字,而不是类型, 例如下图,通过@Component 创建了一个单例Bean, 它的名字是 orderService,通过@Bean 创建了两个单例 Bean,名字分别是 orderService1 和 orderServce2 , 这三个单例 Bean 的类型都是 OrderService
在依赖注入的时候,是先 ByType再ByName, 如果根据类型找到的单例Bean 只有一个,那么就不需要根据名字找了
8. 总结
Spring 的在创建 对象的时候,默认使用无参的构造方法去创建,如果没有无参构造方法或者是有多个构造方法,那么就会去推断构造方法(参考第6节推断构造方法),选定构造方法后就去填充属性,如果属性是多例Bean则直接创建对象,如果是单例Bean,则会通过先ByType 后ByName 的方式到单例池中找到 Bean 对象。