一、核心概念
1、什么是BeanDefinition
定义
BeanDefinition表示Bean定义,Spring根据BeanDefinition来创建Bean对象,BeanDefinition有很多属性用来描述Bean。
BeanDefinition重要属性
beanClass:表示bean的类型,比如UserService.class、OrderService.class,Spring在创建Bean的过程中会根据此属性来实例化得到对象。
scope:表示一个bean的作用域,scope为singleton表示单例,prototype表示原型bean;
isLazy:表示一个bean是不是需要懒加载,原型bean的isLazy属性不起作用,懒加载的单例bean,会在第一次getBean的时候生成该bean,非懒加载的单例bean则会在Spring启动过程中直接生成好。
dependsOn:表示一个bean在创建之前所依赖的其他bean,在bean创建之前,它所依赖的这些bean得全部创建好。
primary:表示一个bean是主bean,在Spring中的一个类型可以多个bean对象,在进行依赖注入时,如果根据类型找到了多个bean。此时会判断这些bean中是否存在一个主bean,如果存在,则直接将这个bean注入给属性。
initMethodName:表示一个bean的初始化方法,一个bean的生命周期过程中有一个步骤叫初始化,Spring会在这个步骤中去调用bean的初始化方法,初始化逻辑由程序员自己控制,表示程序员可以自定义逻辑对bean进行加工。
我们平时用到的@Component、@Bean、<bean/>这些都会解析为BeanDefinition。
2、什么是BeanFactory
定义
BeanFactory是一种Spring容器,也叫Bean工厂,它可以来创建Bean、获取Bean,BeanFactory是Spring中非常核心的组件。
BeanDefinition、BeanFactory、Bean关系
BeanFactory将利用BeanDefinition来生成Bean对象,BeanDefinition相当于BeanFactory的原材料,Bean对象就相当于BeanFactory所生产出来的产品。
BeanFactory的核心子接口和实现类
ListableBeanFactory:
ConfigurableBeanFactory:
AutowireCapableBeanFactory:
AbstractBeanFactory:
DefaultzListableBeanFactory:最重要的,支持单例Bean、支持Bean别名、支持父子 BeanFactory、支持Bean类型转化、支持Bean后置处理、支持FactoryBean、支持自动装配,等待。
3、什么是Bean生命周期
定义
Bean生命周期描述的是Spring中一个Bean创建过程和销毁过程中所经历的步骤,其中Bean创建过程是重点。程序员可以利用Bean生命周期机制对Bean进行自定义加工。
Bean生命周期核心步骤
- BeanDefinition对象创建
- 构造方法推断选出一个构造方法
- 实例化(构造方法反射得到对象)
- 属性填充(依赖注入)
- 初始化(对其他属性赋值、校验)
- 初始化后(AOP、生成代理对象)通过BeanPostProcessor机制实现
4、@Autowired是什么
@Autowired表示某个属性是否需要进行依赖注入,可以写在属性和方法上。注解中的required属性默认为ture,表示如果没有对象可以注入给属性则抛异常。
@Autowired加在某个属性上,Spring在进行Bean的生命周期过程中,在属性填充这一步,会基于实例化出来的对象,对该对象中加了@Autowired的属性自动给属性赋值。
Spring会先根据属性的类型去Spring容器中找出该类型所有的Bean对象,如果找出来多个,则再根据属性的名字从多个中再确定一个。如果required属性为true,并且根据属性信息找不到对象,则直接抛异常。
当@Autowired注解写在某个方法上时,Spring在Bean生命周期的属性填充阶段,会根据方法的参数类型、参数名字从Spring容器找到对象当做方法入参,自动反射调用该方法。
@Autowired加在构造方法上时,Spring会在推断构造方法阶段,选择该构造方法来进行实例化,在反射调用构造方法之前,会先跟你构造参数类型、参数名从Spring容器中找到Bean对象,当做构造方法入参。
5、@Resource是什么
@Resource注解与@Autowired类似,也是用来进行依赖注入的,@Resource是Java层面所提供的注解,@Autowired是Spring所提供的注解,它们依赖注入的底层实现逻辑也不相同。
@Resource注解中有一个name属性,针对name属性是否有值,@Resource的依赖注入底层流程是不同的。
@Resource如果那么属性有值,那么Spring会直接根据指定的name值去Spring容器找到Bean对象,如果找到了则成功,如果没找到则报错。
-
如果@Resource中name属性没有值,则:
先判断该属性名字在Spring容器中是否存在Bean对象,如果存在则成功找到Bean对象进行注入,如果不存在,则根据属性类型去Spring容器找到Bean对象,知道了一个则进行注入。
6、@Value是什么
@Value注解和@Resource、@Autowired类似,也是用来对属性进行依赖注入的,只不过@Value是用来从Properties文件中获取值的,并且@Value可以解析SpEL(Spring表达式)
@Value("heyj") 直接将字符串“heyj”赋值给属性,如果属性类型不是String,或无法进行类型转化则报错。
@Value(" {}中的字符串当做key,从Properties文件中找到对应的value赋值给属性,如果没有找到,则会把"${heyj}"当做普通字符串注入给属性。
@Value("#{heyj}") 会将#{}中的字符串当做Spring表达式进行解析,Spring会把“heyj”当做beanName,并从Spring容器中找到对应bean,如果找到则进行属性注入,没找到则报错。
7、FactoryBean是什么
定义
FactoryBean是Spring所提供的一种较灵活的创建Bean的方式,可以通过实现FactoryBean接口中的getObject()方法来返回一个对象,这个对象就是最终的Bean对象。
FactoryBean接口中的方法
Object getObject(): 返回的是Bean对象
boolean isSingleton(): 返回的是否是单例Bean对象
Class getObjectType(): 返回的是Bean对象的类型
@Component("heyj")
public class HeyjFactoryBean implements FactoryBean {
// Bean对象
@Override
public Object getObject() throws Exception {
return new User();
}
// Bean对象类型
@Override
public Class<?> getObjectType() {
return User.class;
}
// 所定义的Bean是否是单例
public boolean isSingleton() {
return true;
}
}
FactoryBean 的特殊点:
上述代码,实际上对应来两个Bean对象:
beanName为“heyj”,bean对象为getObject方法返回的User对象;
beanName为“&heyj”,bean对象为HeyjFactoryBean类的实例对象。
FactoryBean对象本身也是一个Bean,同时它相当于一个小型工厂,可以生产出另外的Bean。
BeanFactory是一个Spring容器,是一个大型工厂,它可以生产出各种各样的Bean。
FactoryBean机制被广泛的应用在Spring内部和Spring第三方框架或组件的整合过程中。
8、ApplicatonContext是什么
定义
ApplicatonContext是比BeanFactory更加强大的Spring容器,它既可以创建bean,获取bean,还支持国际化、事件广播、获取资源等BeanFactory不具备的功能。
ApplicatonContext所继承的接口
EnvironmentCapable:ApplicatonContext继承了这个接口,表示拥有了获取环境变量的功能,可以通过ApplicationContext获取操作系统环境变量和JVM环境变量。
ListableBeanFactory:ApplicatonContext继承了这个接口,就拥有了获取所有beanNames、判断某个beanName是否存在beanDefinition对象、统计BeanDefinition个数,获取某个类型对应的所有beanNames等功能。
HierarchicalBeanFactory:ApplicatonContext继承了这个接口,就拥有了获取父BeanFactory、判断某个name是否存在bean对象功能。
MessageSource:ApplicatonContext继承了这个接口,就拥有国际化功能,比如可以直接利用MessageSource对象获取某个国际化资源。
ApplicationEventPublisher:ApplicatonContext继承了这个接口,就拥有了事件发布功能,可以发布事件,这是ApplicationContext相对于BeanFactory比较突出、常用的功能。
ResourcePatternResolver:ApplicatonContext继承了这个接口,就拥有了加载并获取资源的功能,这里的资源可以是文件,图片等某个URL资源都可以。
9、BeanPostProcessor是什么
定义
BeanPostProcessor是Spring所提供的一种扩展机制,可以利用该机制对Bean进行定制加工,在Spring底层源码实现中,也广泛的用到该机制,BeanPostProcessor通常也叫做Bean后置处理器。
BeanPostProcessor在Spring中是一个接口,我们定义一个后置处理器,就是提供一个类实现该接口,在Spring中还存在一些接口继承了BeanPostProcessor,这些子接口是在BeanPostProcessor的基础上增加一些其他的功能。
BeanPostProcessor中的方法
postProcessBeforeInitilzation() : 初始化前方法,表示可以利用这个方法来对Bean在初始化前进行自定义加工。
postProcess AfterInitilzation() : 初始化后方法,表示可以利用这个方法来对Bean在初始化后进行自定义加工。
InstantiationAwareBeanPostProcessor
是BeanPostProcessor的一个接口,有3个方法:
postProcessBeforeInstantiation(): 实例化前
postProcessAfterInstantiation():实例化后
postProcessProperties():属性注入后
10、AOP是什么
定义
AOP就是面向切面编程,是一种非常适合在无需修改业务代码的前提下,对某个或某些业务增加统一的功能,比如日志记录、权限控制、事务管理等,能很好的是的代码解藕,提高开发效率。
AOP中的核心概念
Advice:可以理解为通知、建议,在Spring中通过定义Advice来定义代理逻辑。
Pointcut:是切点,表示Advice对应的代理逻辑应用在哪个类、哪个方法上。
Advisor:等于Advisor+Pointcut,表示代理逻辑和切点的一个整体,程序员可以定义或者封装一个Advisor,来定义切点和代理逻辑。
Weaving:表示织入,将Advice代理逻辑在源代码级别嵌入到切点的过程。
Target:表示目标对象,也就是被代理对象,在AOP生成的代理对象中会持有目标对象。
Join Point:表示连接点,在Spring AOP中,就是方法的执行点。
AOP的工作原理:
AOP是发生在Bean的生命周期过程中的:
- Spring生成bean对象时,先实例化出来一个对象,也就是target对象
- 再对target对象进行属性填充
- 在初始化后步骤中,会判断target对象有没有对应的切面
- 如果有切面,就表示当前target对象需要进行AOP
- 通过Cglib或者JDK动态代理机制生成一个代理对象,作为最终的bean对象。
- 代理对象中有一个target属性指向来target对象
二、 Bean的创建
bean的创建方式
�bean标签xml (不做介绍)
@Bean
@Component
BeanDefinition
FactoryBean
@Bean方式
public class Config {
@Bean
public User user() {
return new User();
}
}
public class User {
}
测试:
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
User user = context.getBean("user", User.class);
System.out.println(user);
}
AnnotationConfigApplicationContext的构造方法入参是配置类。
@Component方式
@ComponentScan("com.heyj")
public class Config {
}
@Component
public class User {
}
测试方式同上。配置类上使用注解@ComponentScan指定扫描包路径,然后Spring会扫描该包下带有@Component注解的所有类,并解析为Bean。
同类注解还有@Service,@Rersistory,@Controller等。
BeanDefinition定义Bean
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(User.class);
context.registerBeanDefinition("user", beanDefinition);
context.refresh();
User user = context.getBean("user", User.class);
System.out.println(user);
}
使用BeanDefinition,需要制定bean的类型,并且注册到spring容器中。
FactoryBean机制
@Component
public class HeyjFactoryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
Person person = new Person();
System.out.println(person);
return person;
}
@Override
public Class<?> getObjectType() {
return Person.class;
}
@Override
public boolean isSingleton() {
return FactoryBean.super.isSingleton();
}
}
HeyjFactoryBean这个bean也要纳入spring管理。
测试:
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(HeyjFactoryBean.class);
context.registerBeanDefinition("person", beanDefinition);
context.refresh();
Person person = context.getBean("person", Person.class);
HeyjFactoryBean heyjFactoryBean = context.getBean("&person", HeyjFactoryBean.class);
System.out.println(person);
System.out.println(heyjFactoryBean);
}
其中:
Object getObject(): 返回的是Bean对象
Class getObjectType(): 返回的是Bean对象的类型
如果使用beanName获取bean对象,这个bean对象是getObject的那个对象,&beanName返回是HeyjFactoryBean类型bean。
三、Spring容器
单例池
BeanFactory
ApplicationContext
AnnotationConfigApplicationContext (不可刷新)
ClassPathXmlApplicationContext (可刷新)
FileSystemXmlApplicationContext
单例池
对于作用域scope为singleton的bean,spring会在启动时就把这些bean准备好放在一个单例池中,ConcurrentHashMap<String, Bean对象>,单例bean不代表spring容器中这个类型bean只有一个。
BeanFactory
BeanFactory就是Bean工厂,生产Bean的,它是一个接口,实现类有DefaultListableBeanFactory.
把普通对象直接注册类单例bean
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerSingleton("user", new User());
User user = beanFactory.getBean("user", User.class);
System.out.println(user);
}
也可以注册BeanDefinition
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(User.class);
beanFactory.registerBeanDefinition("user", beanDefinition);
User user = beanFactory.getBean("user", User.class);
System.out.println(user);
}
ApplicationContext
继承了很多接口,可参考上一章节8小节。
四、Bean创建的生命周期
重要的阶段:
生成BeanDefinition
实例化(实例化前、推断构造方法、实例化后)
BeanDefinition的后置处理
填充属性
初始化 (初始化前、初始化、初始化后)
1、Bean后置处理器
通过BeanPostProcessor接口实现
配置类,制定扫描包路径
@ComponentScan("com.heyj")
public class Config {
}
业务类,@Component注解纳入spring容器管理
@Component("userService")
public class UserService {
}
实现BeanPostProcessor接口,并交给Spring容器管理,那么,会在创建bean生命周期的初始化前后调用相应方法。
@Component
public class HeyjBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("调用了postProcessBeforeInitialization " + beanName);
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("调用了postProcessAfterInitialization " + beanName);
return new Person();
}
}
测试代码:
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService);
}
}
打印结果
/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/bin/java ...
调用了postProcessBeforeInitialization config
调用了postProcessAfterInitialization config
调用了postProcessBeforeInitialization userService
调用了postProcessAfterInitialization userService
Exception in thread "main" org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'userService' is expected to be of type 'com.heyj.UserService' but was actually of type 'com.heyj.Person'
说明spring每生产一个bean对象都会调用BeanPostProcessor里的相应方法,并且在创建bean生命周期的最后把一个Person对象返回,导致最后上面日志中的报错现象。postProcessAfterInitialization返回null时spring会做特殊处理。
2、实例化前
通过实现InstantiationAwareBeanPostProcessor接口,重写postProcessBeforeInstantiation方法。
@Component("userService")
public class UserService {
public UserService() {
System.out.println("调用构造方法");
}
}
实现InstantiationAwareBeanPostProcessor接口,重新相应方法。
@Component
public class HeyjBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (beanName.equals("userService")) {
System.out.println("实例化前。。。");
}
return null;
}
}
测试代码
@Component
public class HeyjBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (beanName.equals("userService")) {
System.out.println("实例化前。。。");
}
return null;
}
}
打印结果
实例化前。。。
调用构造方法
com.heyj.UserService@aecb35a
3、实例化--构造方法推断
当有多个构造方法时,会优先选择默认无参数构造方法,如果没有无参构造方法就会报错;
通过@Autowired指定构造方法某一个构造方法,则就使用这个构造方法,如果多个构造方法上都有@Autowired也会报错;
当多个构造方法都有@Autowired(requried=false),则会选择参数多的那一个构造方法。
同等条件多个构造方法,顺序也会有影响,优先前面的。
4、实例化后
实现InstantiationAwareBeanPostProcessor接口重写postProcessAfterInstantiation方法,注意后初始化的接口方法区分。
@Component
public class HeyjBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (beanName.equals("userService")) {
System.out.println("实例化前。。。");
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (beanName.equals("userService")) {
System.out.println("实例化后");
}
return true;
// return false; // 默认返回true,当返回false时初始化后的所有流程就不走了。
}
}
验证初始化后 的 属性赋值流程。
@Component("userService")
public class UserService {
private User user;
public UserService() {
System.out.println("调用构造方法");
}
@Autowired
public void setUser(User user) { // 验证初始化后 的 属性赋值流程。
this.user = user;
System.out.println("setUser 方法");
}
}
@Component
public class User {
}
打印结果
实例化前。。。
调用构造方法
实例化后
setUser 方法 //实例化后的 属性赋值,
com.heyj.UserService@5e955596
因为postProcessAfterInstantiation方法返回true,初始化后的属性赋值也执行了。
如果postProcessAfterInstantiation方法返回false,则初始化后的属性赋值不会执行,将打印如下:
实例化前。。。
调用构造方法
实例化后
com.heyj.UserService@5e955596
5、属性赋值
6、初始化
对应的bean的类实现InitializingBean接口,重写afterPropertiesSet方法。
@Component("userService")
public class UserService implements InitializingBean {
private User user;
public UserService() {
System.out.println("调用构造方法");
}
@Autowired
public void setUser(User user) {
this.user = user;
System.out.println("setUser 方法");
}
@Override
public void afterPropertiesSet() throws Exception {
//
System.out.println("初始化,做一些验证的工作");
}
}
main方法打印如下:
实例化前。。。
调用构造方法
实例化后
setUser 方法
初始化,做一些验证的工作
7、初始化前
可以用@PostConstrut实现,此文不讲这种方式。
实现InstantiationAwareBeanPostProcessor接口的postProcessBeforeInitialization方法
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("userService")) {
System.out.println("初始化前。。");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return InstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}
8、初始化后
同上
实现InstantiationAwareBeanPostProcessor接口的postProcessAfterInitialization方法
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("userService")) {
System.out.println("初始化前。。");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("userService")) {
System.out.println("初始化后--");
}
return InstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}
打印:
实例化前。。。
调用构造方法
实例化后
setUser 方法
初始化前。。
初始化,做一些验证的工作
初始化后--
其实,InstantiationAwareBeanPostProcessor接口也继承了BeanPostProcessor接口。
9、初始化后--AOP
实现BeanPostProcessor接口,重写postProcessAfterInitialization方法:
@Component
public class MyAopBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("userService")) {
Object proxyInstance = Proxy.newProxyInstance(MyAopBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("AOP 代理逻辑1");
method.invoke(bean, args);
System.out.println("AOP 代理逻辑2");
return null;
}
});
return proxyInstance;
}
return bean;
}
}
注意上述后置处理器需要纳入spring容器管理。
因为jdk动态代理需要接口,所以:
public interface UserServiceInterface {
public void test();
}
实现上述接口
@Component("userService")
public class UserService implements InitializingBean, UserServiceInterface {
private User user;
public UserService() {
System.out.println("调用构造方法");
}
@Autowired
public void setUser(User user) {
this.user = user;
System.out.println("setUser 方法");
}
@Override
public void afterPropertiesSet() throws Exception {
//
System.out.println("初始化,做一些验证的工作");
}
@Override
public void test() {
System.out.println("业务逻辑");
}
}
验证:
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
UserServiceInterface userServiceInterface = (UserServiceInterface) context.getBean("userService");
userServiceInterface.test();
}
}
打印:
实例化前。。。
调用构造方法
实例化后
setUser 方法
初始化前。。
初始化,做一些验证的工作
初始化后--
AOP 代理逻辑1
业务逻辑
AOP 代理逻辑2
五、Spring整合MyBaties原理
Spring整合MyBaties后有如下代码比较常见:
@Mapper
public interface UserMapper {
@Query("select 'helloworld'")
String getUserById(String id);
}
@Component("userService")
public class UserService {
@Autowired
private UserMapper userMapper;
}
因为UserMapper是接口,无法实例化变成spring的bean对象。怎么办?
MyBaties会通过Mapper接口使用动态代理生成一个代理对象,然后交给Spring管理。
实际上,利用FactoryBean接口机制,通过getObject返回代理对象,通过编程的方式自定义BeanDefinition,然后注册到Spring容器中。
如果此时再有多个Mapper接口,是不是还要实现FactoryBean接口弄多个实现类呢?显然不合理。
可以在上述实现类中弄一个mapper接口类型的属性,通过构造方法注入进去。
但是,每个Mapper接口还是定义BeanDefinition,然后注册到spring,还是有大量的重复代码?
此时,可以通过@Mapperscan注解指定mapper接口的包路径,进行文件扫描,遍历class文件生成代理对象,然后注册到spring。
六、循环依赖
循环依赖现象:
@Component("aService")
public class AService {
@Autowired
private BService bService;
@Autowired
private CService cService;
}
@Component("bService")
public class BService {
@Autowired
private AService aService;
}
@Component("cService")
public class CService {
@Autowired
private AService aService;
}
以上,AService依赖注入BService,而BService又依赖注入AService,这就导致循环依赖的现象。
更严重性的还有 AService依赖了CService,CService又依赖了AService。
以下分析过程:
竖向时间线
AService的Bean生命周期:
creatingSet.add("aService") 表示AService正在创建bean的生命周期中。。。
实例化(new AService()), AService原始对象 ----> 存入三级缓存
填充bService属性 ----> 从单例池中找 ----> 找不到 ----> 创建BService的Bean
BService的Bean生命周期:
2.1 实例化(new BService()),BService 原始对象
2.2 填充aService属性 ----> 从代理池中找 |二级缓存----> 找不到 ----> creatingSet中有 ----> 发生循环依赖 ---->用三级缓存中的AService原始对象----> AOP ---->AService 代理对象 ----> 放入二级缓存。
2.3 填充其他属性
2.4 做其他重要事情(AOP)
2.5 放入单例池 Bean对象
同样的,填充cService属性 ----> 从单例池中找 ----> 找不到 ----> 创建CService的Bean
CService的bean生命周期:
2.1 实例化(new CService()),CService 原始对象
2.2 填充aService属性 ----> 从代理池中找 ----> 找不到 ----> 二级缓存找 ----> 找到AService代理对象
2.3 填充其他属性
2.4 做其他重要事情(AOP,此处要判断AService是否已经做了AOP?)
可以先从二级缓存中取代理对象
2.5 放入单例池 Bean对象
填充其他属性
做其他重要事情(AOP)
放入单例池 Bean对象
三级缓存
第一级缓存:单例池singletonObjects Map<beanName, Bean对象> 完整的bean
第二级缓存:earlySingletonObjects Map<beanName, Bean对象> 不完整的bean 作用:存放代理对象
第三级缓存:singletonFactories。 Map<beanName, lambda(()->{getEarlyBeanReference(beanName,mbd, bean)})> 作用:AOP
如果使用构造方法进行属性注入时,并且发生循环依赖时,上述三级缓存方案无法解决,因为相当于在实例化之前就要拿到依赖属性的bean,上述不适合了。可以使用@Lazy注解解决,懒加载依赖。