循环依赖和三级缓存
public class MainStart {
private static Map<String,BeanDefinition> beanDefinitionMap=new ConcurrentHashMap<>(256);
public static void loadBeanDefinition(){
BeanDefinition aBeanDefinition=new RootBeanDefinition(InstanceA.class) ;
BeanDefinition bBeanDefinition=new RootBeanDefinition(InstanceB.class) ;
beanDefinitionMap.put("instanceA",aBeanDefinition);
beanDefinitionMap.put("instanceB",bBeanDefinition);
}
public static void main(String[] args) throws Exception {
//加载beanDefinition
loadBeanDefinition();
//循环创建bean
for (String key : beanDefinitionMap.keySet()) {
//先创建A
getBean(key);
}
InstanceA instanceA = (InstanceA) getBean("instanceA");
instanceA.say();
}
//一级缓存
public static Map<String,Object> singletonObjects=new ConcurrentHashMap<>();
public static Object getBean(String beanName) throws IllegalAccessException, InstantiationException {
//出口
Object singleton = getSingleton(beanName);
if(singleton!=null){
return singleton;
}
//实例化
RootBeanDefinition beanDefinition = (RootBeanDefinition)beanDefinitionMap.get(beanName);
Class<?> beanClass = beanDefinition.getBeanClass();
Object instance = beanClass.newInstance();//无参构造函数
//添加到一级缓存中
singletonObjects.put(beanName,instance);
//属性赋值
Field[] declaredFields = beanClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
Autowired annotation = declaredField.getAnnotation(Autowired.class);
if(annotation!=null){
declaredField.setAccessible(true);
// byname bytype
//拿到instanceB
String name = declaredField.getName();
Object fileObject=getBean(name); //拿到B的bean
declaredField.set(instance,fileObject);
}
}
//初始化 init-method
return instance;
}
public static Object getSingleton(String beanName){
if(singletonObjects.containsKey(beanName)){
return singletonObjects.get(beanName);
}
return null;
}
}
为什么要二级缓存和三级缓存
那么为什么一级缓存能解决,还需要2级缓存呢?
俩个线程,第一个线程在创建beanA的时候,属性赋值后加入一级缓存,第二个线程去getBeanA,拿到的是不完整的beanA。所以需要二级缓存
public class MainStart {
private static Map<String,BeanDefinition> beanDefinitionMap=new ConcurrentHashMap<>(256);
public static void loadBeanDefinition(){
BeanDefinition aBeanDefinition=new RootBeanDefinition(InstanceA.class) ;
BeanDefinition bBeanDefinition=new RootBeanDefinition(InstanceB.class) ;
beanDefinitionMap.put("instanceA",aBeanDefinition);
beanDefinitionMap.put("instanceB",bBeanDefinition);
}
public static void main(String[] args) throws Exception {
//加载beanDefinition
loadBeanDefinition();
//循环创建bean
for (String key : beanDefinitionMap.keySet()) {
//先创建A
getBean(key);
}
InstanceA instanceA = (InstanceA) getBean("instanceA");
instanceA.say();
}
//一级缓存
public static Map<String,Object> singletonObjects=new ConcurrentHashMap<>();
//二级缓存,为了将成熟bean和纯净bean分离开,避免读取到不完整的Bean
public static Map<String,Object> earlySingletonObjects=new ConcurrentHashMap<>();
public static Object getBean(String beanName) throws IllegalAccessException, InstantiationException {
//出口
Object singleton = getSingleton(beanName);
if(singleton!=null){
return singleton;
}
//实例化
RootBeanDefinition beanDefinition = (RootBeanDefinition)beanDefinitionMap.get(beanName);
Class<?> beanClass = beanDefinition.getBeanClass();
Object instance = beanClass.newInstance();//无参构造函数
x
//属性赋值
Field[] declaredFields = beanClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
Autowired annotation = declaredField.getAnnotation(Autowired.class);
if(annotation!=null){
declaredField.setAccessible(true);
// byname bytype
//拿到instanceB
String name = declaredField.getName();
Object fileObject=getBean(name); //拿到B的bean
declaredField.set(instance,fileObject);
}
}
//初始化 init-method
//添加到一级缓存中
singletonObjects.put(beanName,instance);
return instance;
}
public static Object getSingleton(String beanName){
if(singletonObjects.containsKey(beanName)){
return singletonObjects.get(beanName);
}else if(earlySingletonObjects.containsKey(beanName)){
return earlySingletonObjects.get(beanName);
}
return null;
}
}
再来说下三级缓存
假设A使用了AOP @Pointcut("execution(* *..InstanceA.*(..))")
,,切点命中了A,要给A创建动态代理
放在初始化后创建,B里的A就不是动态代理了。其实Spring在初始化之后也使用了bean的后置处理器去创建了动态代理。
创建Bean的时候在哪里创建了动态代理?
- 在实例化之后
- 当出现了循环依赖会在实例化之后调用
用动态代理的方式解决
模拟一个bean的后置处理器
public class JdkProxyBeanPostProcessor implements
SmartInstantiationAwareBeanPostProcessor {
@Override
public Object getEarlyBeanReference(Object bean, String beanName)
throws BeansException {
// 假设:A 被切点命中
// 需要创建代理 @PointCut("execution(* *..InstanceA.*(..))")
/*判断是不是被增强的类,是不是需要创建动态代理*/
if(bean instanceof InstanceA) {
JdkDynimcProxy jdkDynimcProxy = new JdkDynimcProxy(bean);
return jdkDynimcProxy.getProxy();
}
return bean;
}
}
JdkDynimcProxy
动态代理类,动态代理不理解的看我上篇就懂了
正常情况下会在初始化之后创建动态代理,Spring还是希望正常的Bean 还是在初始化后创建。
只在循环依赖的情况下在实例化后创建proxy。所以关键是判断当前是不是循环依赖。那么怎么判断?
二级缓存中有就说明是循环依赖,应该在出口getSingleton
去判断
public static Object getSingleton(String beanName){
//先从一级缓存拿
if(singletonObjects.containsKey(beanName)){
return singletonObjects.get(beanName);
}
//再去二级缓存拿
else if(earlySingletonObjects.containsKey(beanName)){
//就说明是循环依赖
//创建动态代理
Object obj = new JdkProxyBeanPostProcessor().getEarlyBeanReference(earlySingletonObjects.get(beanName), beanName);//instance:bean实例,beanName:bean名称
earlySingletonObjects.put(beanName,obj);
return earlySingletonObjects.get(beanName);
}
return null;
}
JdkProxyBeanPostProcessor这个是后置处理器,如果在getBean的时候写,不符合标准。后置处理器是在bean的创建过程中去给它增强的
三级缓存是为了单一职责
所以创建动态代理还是希望在实例化之后创建
那么getSingleton
在下面,所以可以用到函数接口。所以三级缓存就是存函数接口的
@FunctionalInterface
public interface ObjectFactory<T> {
/**
* 返回此工厂管理的对象的实例(可能是共享的或独立的)
*/
T getObject() throws BeansException;
}
// 三级缓存
public static Map<String,ObjectFactory> singletonFactories=
new ConcurrentHashMap<>();
singletonFactories.put(beanName,new ObjectFactory(){
@Override
public Object getObject() throws BeansException {
return new JdkProxyBeanPostProcessor().getEarlyBeanReference(earlySingletonObjects.get(beanName), beanName);;
}
});
二级缓存也不用存了
加入循环依赖标识
//循环依赖标识
public static Set<String> singletonsCurrentlyInCreation=new HashSet<>();
最后贴上完整代码
public class MainStart {
private static Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/**
* 读取bean定义,当然在spring中肯定是根据配置 动态扫描注册
*/
public static void loadBeanDefinitions() {
RootBeanDefinition aBeanDefinition=new RootBeanDefinition(InstanceA.class);
RootBeanDefinition bBeanDefinition=new RootBeanDefinition(InstanceB.class);
beanDefinitionMap.put("instanceA",aBeanDefinition);
beanDefinitionMap.put("instanceB",bBeanDefinition);
}
public static void main(String[] args) throws Exception {
// 加载了BeanDefinition
loadBeanDefinitions();
// 注册Bean的后置处理器
// 循环创建Bean
for (String key : beanDefinitionMap.keySet()){
// 先创建A
getBean(key);
}
InstanceA instanceA = (InstanceA) getBean("instanceA");
instanceA.say();
}
// 一级缓存
public static Map<String,Object> singletonObjects=new ConcurrentHashMap<>();
// 二级缓存: 为了将 成熟Bean和纯净Bean分离,避免读取到不完整得Bean
public static Map<String,Object> earlySingletonObjects=new ConcurrentHashMap<>();
// 三级缓存
public static Map<String,ObjectFactory> singletonFactories=new ConcurrentHashMap<>();
// 循环依赖标识
public static Set<String> singletonsCurrennlyInCreation=new HashSet<>();
// 假设A 使用了Aop @PointCut("execution(* *..InstanceA.*(..))") 要给A创建动态代理
// 获取Bean
public static Object getBean(String beanName) throws Exception {
Object singleton = getSingleton(beanName);
if(singleton!=null){
return singleton;
}
// 正在创建
if(!singletonsCurrennlyInCreation.contains(beanName)){
singletonsCurrennlyInCreation.add(beanName);
}
// createBean
// 实例化
RootBeanDefinition beanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
Class<?> beanClass = beanDefinition.getBeanClass();
Object instanceBean = beanClass.newInstance(); // 通过无参构造函数
// 创建动态代理 (耦合 、BeanPostProcessor) Spring还是希望正常的Bean 还是再初始化后创建
// 只在循环依赖的情况下在实例化后创建proxy 判断当前是不是循环依赖
final Object temp=instanceBean;
singletonFactories.put(beanName, new ObjectFactory() {
@Override
public Object getObject() throws BeansException {
System.out.println("执行函数接口");
return new JdkProxyBeanPostProcessor().getEarlyBeanReference(temp,beanName);
}
});
// 属性赋值
Field[] declaredFields = beanClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
Autowired annotation = declaredField.getAnnotation(Autowired.class);
// 说明属性上面有Autowired
if(annotation!=null){
declaredField.setAccessible(true);
// byname bytype byconstrator
// instanceB
String name = declaredField.getName();
Object fileObject= getBean(name); //拿到B得Bean
declaredField.set(instanceBean,fileObject);
}
}
// 初始化 init-mthod
// 放在这里创建已经完了 B里面的A 不是proxy
// 正常情况下会再 初始化之后创建proxy
// 由于递归完后A 还是原实例,, 所以要从二级缓存中拿到proxy 。
if(earlySingletonObjects.containsKey(beanName)){
instanceBean=earlySingletonObjects.get(beanName);
}
// 添加到一级缓存 A
singletonObjects.put(beanName,instanceBean);
// remove 二级缓存和三级缓存
return instanceBean;
}
public static Object getSingleton(String beanName){
// 先从一级缓存中拿
Object bean = singletonObjects.get(beanName);
// 说明是循环依赖
if(bean==null && singletonsCurrennlyInCreation.contains(beanName)){
bean=earlySingletonObjects.get(beanName);
// 如果二级缓存没有就从三级缓存中拿
if(bean==null) {
// 从三级缓存中拿
ObjectFactory factory = singletonFactories.get(beanName);
if (factory != null) {
bean=factory.getObject(); // 拿到动态代理
earlySingletonObjects.put(beanName, bean);
}
}
}
return bean;
}
}