用手写循环依赖的方式来,了解Spring循环依赖

循环依赖和三级缓存

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的时候在哪里创建了动态代理?

  1. 在实例化之后
  2. 当出现了循环依赖会在实例化之后调用

用动态代理的方式解决

模拟一个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;

    }

}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值