前言: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;
}
}