一.说明
- 1.一级缓存的循环依赖问题,执行会报栈溢出异常
- 2.一级缓存也可以解决循环依赖问题,即对象被new出来后立即放到一级缓存中
- 3.但是多线程情况下,线程A在对象被new出来后还要进行依赖注入属性,线程B此时getBean,会得到不完全的Bean
- 4.如果多线程情况下,通过加锁的方式同步代码,假如BeanA已创建好,此时在创建BeanB,A线程想获取BeanA,由于BeanB的创建逻辑被锁,A线程需等待完成后才能执行,影响效率
- 5.因此引入二级缓存
二.代码示例
package com.learning.circulardependency;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Author wangyouhui
* @Description 循环依赖
**/
public class MyApplicationContext {
// 单例 解决线程安全: 双重检查锁
private Map<String, BeanDefinition> beanDefinitionMap = new LinkedHashMap<>();
// 一级缓存 单例池 问题:早期的bean和完整bean放在一起,会出现并发下获取不完的bean
// 所有完整的bean
private final Map<String,Object> singletonObjects = new ConcurrentHashMap<>();
public MyApplicationContext() throws Exception{
// 加载ioc容器:创建所有的Bean
refresh();
}
// ioc容器加载
private void refresh() throws Exception{
// 解析配置 注册BeanDefinition
loadBeanDefinitions();
// 创建所有单例Bean
finishBeanFactoryInitialization();
}
/**
* 创建所有的Bean
*/
private void finishBeanFactoryInitialization() throws Exception{
for (String beanName : beanDefinitionMap.keySet()) {
getBean(beanName);
}
}
/**
* 根据beanName创建Bean
*/
public Object getBean(String beanName) throws Exception {
// 判断Bean是否已经创建好。如果已经创建好了就直接返回,如果没有创建就开始创建
Object bean = getSingleton(beanName);
if(bean != null){
return bean;
}
//1. 实例化
RootBeanDefinition beanDefinition = (RootBeanDefinition)beanDefinitionMap.get(beanName);
Class<?> beanClass = beanDefinition.getBeanClass();
bean = beanClass.newInstance();
//2. 属性注入
Field[] declaredFields = beanClass.getDeclaredFields();
for (Field field : declaredFields) {
// 拿到属性的Autowired注解
Autowired autowired = field.getAnnotation(Autowired.class);
// 如果有@Autowired,就要进行注入
if(autowired != null){
// spring中先根据类型找,如果类型都一样,再根据名字找
// 这里按名字找
String name = field.getName();
Object dependentBean = getBean(name);
// 设置下访问权限
field.setAccessible(true);
field.set(bean, dependentBean);
}
}
//3. 初始化
if(bean instanceof InitializingBean){
InitializingBean initializingBean = (InitializingBean) bean;
initializingBean.afterPropertiesSet();
}
//4. 将bean放入一级缓存
singletonObjects.put(beanName, bean);
return bean;
}
/**
* 创建Bean是否创建
* @param beanName
*/
private Object getSingleton(String beanName) {
if(singletonObjects.containsKey(beanName)){
return singletonObjects.get(beanName);
}
return null;
}
/**
* 根据配置信息创建BeanDefinition 会根据配置信息动态创建
*/
private void loadBeanDefinitions() {
// 创建A BeanDefition
RootBeanDefinition aBeanDefinition = new RootBeanDefinition(InstanceA.class);
// 创建B BeanDefinition
RootBeanDefinition bBeanDefinition = new RootBeanDefinition(InstanceB.class);
beanDefinitionMap.put("instanceA", aBeanDefinition);
beanDefinitionMap.put("instanceB", bBeanDefinition);
}
public static void main(String[] args) throws Exception {
MyApplicationContext context = new MyApplicationContext();
InstanceA instanceA = (InstanceA)context.getBean("instanceA");
System.out.println(instanceA);
}
}