Spring的IOC依赖的处理方式的演示

前言:spring在getBean的时候,能够自动处理加载依赖的bean,即先实例化初始化依赖bean,然后再实例化本bean,这个过程中依赖以及循环依赖的校验是怎么处理的,我们用一个小案例进行演示。

1、概述

我们自制一个集BeanDefinition注册,bean实例化,依赖校验和依赖关系注册等等一系列功能为一体的BeanFacotry,即把spring继承各种接口的功能基于一体的BeanFaoctry(DefaultListableBeanFactory)。首先这个BeanFactory需要有能够存储Beandifition的容器,我们和spring一样,用了一个Map装BeanDefition,另外这个BeanFacotry需要另外一个Map容器,装bean被依赖的关系,我们用 Map<String, Set<String>>存储。

    BeanDefinition主要有几个属性,一个name即是注册bean的id,一个是它依赖了Bean的名称的list集合,还有一个就是Bean的实例(如果创建实例后,不为null)。

class BeanDefinition {
	private Bean bean; // bean初始化后
	private String name; // 和id一致,并且创建bean的时候,设置成
	private String[] dependsOn; // 此bean的依赖的名称

    spring得到的Bean是一个Object类型,我们用一个固定的pojo类Bean来代替简化,它也是非常简单,就一个name属性(和BeanDefinition的id一致),一个list集合装依赖的Bean。

class Bean {
    private String name;
    private List<Bean> list = new ArrayList<>(); // 引用的bean

  2、DefaultListableBeanFactory的功能

1) 注册和获取Beandifition的功能, 即将Beandifition存入内部map中,获取也是从map中根据id取。

        public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
            this.beanDefinitionMap.put(beanName, beanDefinition);
        }
    
        public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
            BeanDefinition bd = this.beanDefinitionMap.get(beanName);
            return bd;
        }

2) 校验依赖,以及存储依赖关系。

校验依赖即是我们要创建的Bean,需要找它的依赖时,对这些依赖进行创建,如果这些依赖同样也依赖要创建的Bean, 那么这个就会出现循环依赖,(当前-依赖先getBean-依赖的依赖时当前-当前getBean...)。

由于我们在BeanDefinition主要存储了当前类依赖于哪些类,而校验的时候需要知道,当前类被哪些依赖,这个就需要注册当前类被哪些类依赖关系到BeanFactory中。

/**
		 * 注册beanName被那个依赖
		 */
		public void registerDependentBean(String beanName, String dependentBeanName) {
			Set<String> dependentBeans = this.dependentBeanMap.get(beanName);
			if (dependentBeans != null && dependentBeans.contains(dependentBeanName)) {
				return;
			}
			synchronized (this.dependentBeanMap) {
				dependentBeans = this.dependentBeanMap.get(beanName);
				if (dependentBeans == null) {
					dependentBeans = new LinkedHashSet<String>(8);
					this.dependentBeanMap.put(beanName, dependentBeans);
				}
				dependentBeans.add(dependentBeanName);
			}
		}
	
		/**
		 * 判断是否依赖: beanName是否是dependsOnBean的依赖
		 */
		protected boolean isDependent(String beanName, String dependentBeanName) {
			return isDependent(beanName, dependentBeanName, null);
		}
	
		private boolean isDependent(String beanName, String dependentBeanName, Set<String> alreadySeen) {
			if (alreadySeen == null) {
				alreadySeen = new HashSet<String>();
			}
			if (alreadySeen.contains(beanName)) {
				return false;
			}
			Set<String> dependentBeans = this.dependentBeanMap.get(beanName);
			if (dependentBeans == null) {
				return false;
			}
			if (dependentBeans.contains(dependentBeanName)) {
				return true;
			}
			for (String transitiveDependency : dependentBeans) { // beanName被依赖的bean是否dependentBeanName
				alreadySeen.add(beanName);
				if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
					return true;
				}
			}
			return false;
		}

3) 获取Bean等功能
        getBean系列功能有bean存在就返回,没有创建,依赖处理等等一些细节操作,我们按spring中的方法名,简易的进行处理。 从doGetBean方法,如果bean已经创建,直接返回,如果有依赖,先对依赖的bean进行getBean操作,其中进行了循环依赖的校验,保证创建方法前,当前要创建的Bean的依赖是创建了的。

public Bean getBean(String name) {
			return doGetBean(name);
		}
	
		private Bean doGetBean(String beanName) {
			BeanDefinition bd = getBeanDefinition(beanName);
			if (bd != null && bd.getBean() != null) {
				return bd.getBean();
			}
			String[] dependsOn = bd.getDependsOn();
			if (dependsOn != null) {
				for (String dependsOnBean : dependsOn) { // dependsOnBean本身是beanName依赖
					if (isDependent(beanName, dependsOnBean)) { // beanName是dependsOnBean依赖
						throw new BeanCreationException("循环依赖...");
					}
					registerDependentBean(dependsOnBean, beanName);
					getBean(dependsOnBean);
				}
			}
			return createBean(beanName, bd);
		}
	
		/**当前bean创建时,依赖的bean,一定创建好了,直接set进去即可。 */
		private Bean createBean(String name, BeanDefinition bd) {
			Bean bean = new Bean();
			bean.setName(name);
			bd.setBean(bean);
			String[] dependsOn = bd.getDependsOn();
			if (dependsOn != null) {
				for (String depend : dependsOn) {
					BeanDefinition beanDefinition = getBeanDefinition(depend);
					Bean dependBean = beanDefinition.getBean();
					if (dependBean != null) {
						bean.getList().add(dependBean);
					}
				}
			}
			return bean;
		}

3、进行测试

public static void main(String[] args) throws Exception {
			BeanDefinition root = new BeanDefinition("Root");
			BeanDefinition child = new BeanDefinition("Child");
			root.setDependsOn(new String[] { child.getName() });
			// child.setDependsOn(new String[]{root.getName()}); // 如果不注释就是循环引用!!!
			DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
			factory.registerBeanDefinition(root.getName(), root);
			factory.registerBeanDefinition(child.getName(), child);
			factory.preInstantiateSingletons();
			Bean bean1 = factory.getBean(root.getName());
			System.out.println(bean1);
		}

    4、完整demo

/**
 * Spring的IOC依赖的处理方式的演示
 */
public class Dependence {

	public static void main(String[] args) throws Exception {
		BeanDefinition root = new BeanDefinition("Root");
		BeanDefinition child = new BeanDefinition("Child");
		root.setDependsOn(new String[] { child.getName() });
		// child.setDependsOn(new String[]{root.getName()}); // 如果不注释就是循环引用!!!
		DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
		factory.registerBeanDefinition(root.getName(), root);
		factory.registerBeanDefinition(child.getName(), child);
		factory.preInstantiateSingletons();
		Bean bean1 = factory.getBean(root.getName());
		System.out.println(bean1);
	}

}

/**
 * 综合了各个层级BeanFactory的能力的类
 */
class DefaultListableBeanFactory {

	/**
	 * 装bean的定义
	 */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);

	/**
	 * 装key的BeanDefinition被哪些依赖
	 */
	private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<String, Set<String>>(64);

	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}

	public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		BeanDefinition bd = this.beanDefinitionMap.get(beanName);
		return bd;
	}

	/**
	 * 注册beanName被那个依赖
	 */
	public void registerDependentBean(String beanName, String dependentBeanName) {
		Set<String> dependentBeans = this.dependentBeanMap.get(beanName);
		if (dependentBeans != null && dependentBeans.contains(dependentBeanName)) {
			return;
		}
		synchronized (this.dependentBeanMap) {
			dependentBeans = this.dependentBeanMap.get(beanName);
			if (dependentBeans == null) {
				dependentBeans = new LinkedHashSet<String>(8);
				this.dependentBeanMap.put(beanName, dependentBeans);
			}
			dependentBeans.add(dependentBeanName);
		}
	}

	/**
	 * 判断是否依赖: beanName是否是dependsOnBean的依赖
	 */
	protected boolean isDependent(String beanName, String dependentBeanName) {
		return isDependent(beanName, dependentBeanName, null);
	}

	private boolean isDependent(String beanName, String dependentBeanName, Set<String> alreadySeen) {
		if (alreadySeen == null) {
			alreadySeen = new HashSet<String>();
		}
		if (alreadySeen.contains(beanName)) {
			return false;
		}
		Set<String> dependentBeans = this.dependentBeanMap.get(beanName);
		if (dependentBeans == null) {
			return false;
		}
		if (dependentBeans.contains(dependentBeanName)) {
			return true;
		}
		for (String transitiveDependency : dependentBeans) { // beanName被依赖的bean是否dependentBeanName
			alreadySeen.add(beanName);
			if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 实例化所有的单例bean
	 */
	public void preInstantiateSingletons() throws Exception {
		for (String benaName : beanDefinitionMap.keySet()) {
			getBean(benaName);
		}
	}

	public Bean getBean(String name) {
		return doGetBean(name);
	}

	private Bean doGetBean(String beanName) {
		BeanDefinition bd = getBeanDefinition(beanName);
		if (bd != null && bd.getBean() != null) {
			return bd.getBean();
		}
		String[] dependsOn = bd.getDependsOn();
		if (dependsOn != null) {
			for (String dependsOnBean : dependsOn) { // dependsOnBean本身是beanName依赖
				if (isDependent(beanName, dependsOnBean)) { // beanName是dependsOnBean依赖
					throw new BeanCreationException("循环依赖...");
				}
				registerDependentBean(dependsOnBean, beanName);
				getBean(dependsOnBean);
			}
		}
		return createBean(beanName, bd);
	}

	/**
	 * 当前bean创建时,依赖的bean,一定创建好了,直接set进去即可。
	 */
	private Bean createBean(String name, BeanDefinition bd) {
		Bean bean = new Bean();
		bean.setName(name);
		bd.setBean(bean);
		String[] dependsOn = bd.getDependsOn();
		if (dependsOn != null) {
			for (String depend : dependsOn) {
				BeanDefinition beanDefinition = getBeanDefinition(depend);
				Bean dependBean = beanDefinition.getBean();
				if (dependBean != null) {
					bean.getList().add(dependBean);
				}
			}
		}
		return bean;
	}
}

/**
 * Bean
 */
class Bean {
	private String name;
	private List<Bean> list = new ArrayList<>(); // 引用的bean

	public List<Bean> getList() {
		return list;
	}

	public void setList(List<Bean> list) {
		this.list = list;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Bean [name=" + name + ", list=" + list + "]";
	}
}

/**
 * BeanDefinition的定义
 */
class BeanDefinition {
	private Bean bean; // bean初始化后
	private String name; // 和id一致,并且创建bean的时候,设置成
	private String[] dependsOn; // 此bean的依赖的名称

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String[] getDependsOn() {
		return dependsOn;
	}

	public void setDependsOn(String[] dependsOn) {
		this.dependsOn = dependsOn;
	}

	public BeanDefinition(String name) {
		super();
		this.name = name;
	}

	public Bean getBean() {
		return bean;
	}

	public void setBean(Bean bean) {
		this.bean = bean;
	}
}

猜你喜欢

转载自blog.csdn.net/shuixiou1/article/details/113406879