本文共 9564 字,大约阅读时间需要 31 分钟。
前言: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 Listlist = 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) { SetdependentBeans = 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 (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 alreadySeen) { if (alreadySeen == null) { alreadySeen = new HashSet (); } if (alreadySeen.contains(beanName)) { return false; } Set 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 MapbeanDefinitionMap = new ConcurrentHashMap (64); /** * 装key的BeanDefinition被哪些依赖 */ private final Map > dependentBeanMap = new ConcurrentHashMap >(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 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 (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 alreadySeen) { if (alreadySeen == null) { alreadySeen = new HashSet (); } if (alreadySeen.contains(beanName)) { return false; } Set 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 list = new ArrayList<>(); // 引用的bean public List getList() { return list; } public void setList(List 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; }}
转载地址:http://fruni.baihongyu.com/