博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring的IOC依赖的处理方式的演示
阅读量:4074 次
发布时间:2019-05-25

本文共 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 List
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
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; }

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
beanDefinitionMap = 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/

你可能感兴趣的文章
uSurvival 1.41多人在线生存逃杀吃鸡类游戏源码
查看>>
玩转@Git三剑客
查看>>
Unity实现c#热更新方案探究(一)
查看>>
uSurvival 1.41多人在线生存逃杀吃鸡类游戏源码
查看>>
AXURE RP8 - 实战手册 网站和APP原型制作案例精粹
查看>>
c#传不确定的参数个数,比如int型
查看>>
python3调用腾讯AI开放平台
查看>>
vector的push_back对于拷贝构造和赋值操作的调用
查看>>
OpenSees开发(一)windows 上编译opensees (使用vs2005)
查看>>
小议函数指针
查看>>
WEB服务器、应用程序服务器、HTTP服务器区别
查看>>
用户名称修改的完美解决方法
查看>>
discuz 3 头像显示不成功
查看>>
Discuz!X3.2 uc_server密码正确无法登录的解决方法
查看>>
spring boot redis 接入笔记
查看>>
ajax 跨域 session 及 spring boot分布式session
查看>>
spring boot 及 redis 实现分布式session 实践笔记
查看>>
TCP协议与UDP协议的区别
查看>>
SpringMVC与Struts2区别与比较总结
查看>>
get与post区别
查看>>