博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring源码(一)---BeanFactory
阅读量:7019 次
发布时间:2019-06-28

本文共 14329 字,大约阅读时间需要 47 分钟。

hot3.png

    Spring IOC 是Spring最核心的东西,对Bean的管理是Spring的核心,然后其他功能都是在Bean容器基础上进行扩展的。Spring容器这块我们重点介绍两个大块:一个是BeanFactory,一个是ApplicationContext。这两者的关系是包含关系,ApplicationContext包含了BeanFactory功能,同时又扩展了事件,消息,资源等方面的东西。

BeanFactory

    BeanFactory类层级关系

112143_P5zr_223302.png

    从这个类图层级结构上看主要分为左右两大部分,左半部分主要定义了BeanFacotry相关的接口,右半部分主要定义了BeanRegistry相关的接口。

    从这个类图我们自上而下逐布分析,该类图结构很清晰,一般是一个接口对应一个抽象类的相关实现,一直到最后进行融合都集中到DefaultListableBeanFactory。我们先大体介绍上面的类图结构,然后在介绍下BeanDefinition,及BeanFactory工作流程。


BeanDefinitionRegistry:主要定义了BeanDefinition注册接口。这个接口的实现就是最后到DefaultListableBeanFactory才实现的。

AliasRegistry:这个顶级接口主要是为了管理别名的。对应的实现类主要是SimpleAliasRegistry,内部维护了一个map,来维护对应的关系。


现在开始介绍BeanFactory主线方面的接口。

BeanFactory:这个Factory的顶级接口,主要定义了Factory最重要的接口,比如getBean等。

SingletonBeanRegistry:这个接口主要定义了单例bean管理相关的接口,如registerSingleton,getSingleton等。

HierarchicalBeanFactory:这个层级BeanFactory主要定义了BeanFactory可以包含父Factory功能的相关接口。

ConfigurableBeanFactory:继承了HierarchicalBeanFactory,这个接口的作用主要是定义了一些Factory的配置接口,比如setBeanClassLoader,setParentBeanFactory,addBeanPostProcessor,等等。采用Builder模式,一步一步组装Factory。

ListableBeanFactory:这个接口的作用主要定义了如何枚举一个Factory中的相关类,而不是通过name一个一个去获取,比如该接口定了getBeanNamesForType,getBeanNamesForAnnotation,getBeansWithAnnotation等等,都是以数组,集合等方式返回多个满足需求的结果。

AutowireCapableBeanFactory:这个接口主要定义了创建bean,自动注入等相关的接口。

ConfigurableListableBeanFactory:这个接口从名字上看把ConfigurableBeanFactory,ListableBeanFactory,AutowireCapableBeanFactory三个结合融合在一起,并做了扩展主要提供了分析修改bean definitions的工具,和对单例bean的预实例化(preInstantiateSingletons)。这个接口可以说是上面介绍所有的接口大融合,涵盖了BeanFactory所需的大部分方法。


具体接口实现

DefaultSingletonBeanRegistry:这个类主要实现了SingletonBeanRegistry,定义了单例bean的注册获取功能。内部实现通过ConcurrentHashMap来维护bean实例。

FactoryBeanRegistrySupport:该类继承DefaultSingletonBeanRegistry,扩展了FactoryBean需要的相关方法。因为FactoryBean是一种特殊的SingletonBean。

AbstractBeanFactory:该类继承了FactoryBeanRegistrySupport,实现了接口ConfigurableBeanFactory定义的相关功能。

AbstractAutowireCapableBeanFactory:该类继承了AbstractBeanFactory,同时实现接口AutowireCapableBeanFactory相关功能。

DefaultListableBeanFactory:这个是总的BeanFactory的实现,同时它本身实现了BeanDefinitionRegistry接口定义的功能,并继承了AbstractAutowireCapableBeanFactory(主要对应ConfigurableListableBeanFactory接口的实现)。

这里提下XmlBeanFactory:该类扩展了DefaultListableBeanFactory,方便的从xml文档中读取bean definitions;该类借助XmlBeanDefinitionReader实现,作用等同于把XmlBeanDefinitionReader和DefaultListableBeanFactory简单的包装。


    从上面三大块对类图结构的介绍我们可以看到spring 采用接口细化,逐级继承,然后逐级实现相关功能。直到最后全部功能实现。结构清晰,利于扩展及复用。

    BeanFacotry运行流程

    这里先介绍下BeanDefinition。BeanDefinition主要描述了一个bean实例。包含范围(单例or原型),bean Class类型,实例的属性值,构造参数值等等,可以说是一个类需要实例化需要的基本元数据。我们平时在xml配置的bean信息都会转变为BeanDefinition。AbstractBeanDefinition作为BeanDefinition 的抽象实现。然后该类有三个具体的实现类:

ChildBeanDefinition: Bean definition for beans which inherit settings from their parent. Child bean definitions have a fixed dependency on a parent bean definition.(直接从sping文档中摘取)

RootBeanDefinition: A root bean definition represents the merged bean definition that backs a specific bean in a Spring BeanFactory at runtime. It might have been created from multiple original bean definitions that inherit from each other, typically registered as GenericBeanDefinition . A root bean definition is essentially the 'unified' bean definition view at runtime.(主要是spring运行时内部可以用来合并多个definition

GenericBeanDefinition:一站式标准的bean definition。像任何bean definition,它允许为指定的类添加构造参数值和属性值。并且可以指定parentName,灵活的从父Bean definition进行派生。一般来说,用GenericBeanDefinition用来注册用户可见的bean definition。父子关系需要预定义的地方 RootBeanDefinition/ChildBeanDefinition。

    这里如果读者想自己调试运行代码 可以直接git clone spring源码,然后按照导入说明导入即可,不过加载的时间很长。

我们先定义个class

//先定义一个普通的java类public class Person {    private String name;    private Integer age;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }}//测试代码@Testpublic void testPerson() {   DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();   //用Properties拼装出BeanDefinitions所需的参数值。   Properties p = new Properties();   p.setProperty("yao.(class)", Person.class.getName());   p.setProperty("yao.age", "18");   p.setProperty("yao.name", "robin");   //把p转化为beanDefinition并注册到beanFactory中。   //如果不写scope,beanFactory默认产生单例bean。   (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);   Person p1 = (Person) lbf.getBean("yao");   Person p2 = (Person) lbf.getBean("yao");   assertTrue("Non null", p1 != null);   assertTrue("Singletons equal", p1 == p2);   lbf = new DefaultListableBeanFactory();   p = new Properties();   p.setProperty("yao.(class)", Person.class.getName());   p.setProperty("yao.age", "18");   p.setProperty("yao.name", "robin");   //修改scope   p.setProperty("yao.(scope)", "prototype");   (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);    p1 = (Person) lbf.getBean("yao");    p2 = (Person) lbf.getBean("yao");   assertTrue("Non null", p1 != null);   assertTrue("Prototypes NOT equal", p1 != p2);}

    bean生成的简单过程:先是通过参数值转化成BeanDefinition,注册到BeanFactory中,通过getBean获取具体实例。

下面我们一步一步debug ,摘取重要代码:

第一步:registerBeanDefinitions

//类PropertiesBeanDefinitionReaderpublic int registerBeanDefinitions(Map
 map, String prefix, String resourceDescription)      throws BeansException {         --------代码省略 具体可去看spring源码-----      String keyString = (String) key;      if (keyString.startsWith(prefix)) {          --------代码省略 具体可去看spring源码-----         if (sepIdx != -1) {            //从property中截取我们的beanName            String beanName = nameAndProperty.substring(0, sepIdx);                     //判断我们注册容器中是否有该bean            if (!getRegistry().containsBeanDefinition(beanName)) {               // If we haven't already registered it...               registerBeanDefinition(beanName, map, prefix + beanName, resourceDescription);               ++beanCount;            }         }        --------代码省略 具体可去看spring源码-----      }   }   return beanCount;}protected void registerBeanDefinition(String beanName, Map
 map, String prefix, String resourceDescription)      throws BeansException {   String className = null;   String parent = null;   //默认的scope 主要是这个代码   String scope = GenericBeanDefinition.SCOPE_SINGLETON;   boolean isAbstract = false;   //是否延迟初始化   boolean lazyInit = false;   ConstructorArgumentValues cas = new ConstructorArgumentValues();   MutablePropertyValues pvs = new MutablePropertyValues();   //遍历我们添写的属性值 name age 类名字等待。   for (Map.Entry
 entry : map.entrySet()) {      String key = StringUtils.trimWhitespace((String) entry.getKey());      if (key.startsWith(prefix + SEPARATOR)) {         String property = key.substring(prefix.length() + SEPARATOR.length());         //从map中解析我们的className         if (CLASS_KEY.equals(property)) {            className = StringUtils.trimWhitespace((String) entry.getValue());         }         else if (PARENT_KEY.equals(property)) {            parent = StringUtils.trimWhitespace((String) entry.getValue());         }         else if (ABSTRACT_KEY.equals(property)) {            String val = StringUtils.trimWhitespace((String) entry.getValue());            isAbstract = TRUE_VALUE.equals(val);         }         //解析scope         else if (SCOPE_KEY.equals(property)) {            // Spring 2.0 style            scope = StringUtils.trimWhitespace((String) entry.getValue());         }         //         else if (SINGLETON_KEY.equals(property)) {            // Spring 1.2 style            String val = StringUtils.trimWhitespace((String) entry.getValue());            scope = ((val == null || TRUE_VALUE.equals(val) ? GenericBeanDefinition.SCOPE_SINGLETON :                  GenericBeanDefinition.SCOPE_PROTOTYPE));         }         else if (LAZY_INIT_KEY.equals(property)) {            String val = StringUtils.trimWhitespace((String) entry.getValue());            lazyInit = TRUE_VALUE.equals(val);         }         //构造参数         else if (property.startsWith(CONSTRUCTOR_ARG_PREFIX)) {            if (property.endsWith(REF_SUFFIX)) {               int index = Integer.parseInt(property.substring(1, property.length() - REF_SUFFIX.length()));               cas.addIndexedArgumentValue(index, new RuntimeBeanReference(entry.getValue().toString()));            }            else {               int index = Integer.parseInt(property.substring(1));               cas.addIndexedArgumentValue(index, readValue(entry));            }         }         else if (property.endsWith(REF_SUFFIX)) {            // This isn't a real property, but a reference to another prototype            // Extract property name: property is of form dog(ref)            property = property.substring(0, property.length() - REF_SUFFIX.length());            String ref = StringUtils.trimWhitespace((String) entry.getValue());            // It doesn't matter if the referenced bean hasn't yet been registered:            // this will ensure that the reference is resolved at runtime.            Object val = new RuntimeBeanReference(ref);            pvs.add(property, val);         }         else {         // 类实例本身需要的正常属性值            pvs.add(property, readValue(entry));         }      }   }--------代码省略 具体可去看spring源码-----   if (parent == null && className == null && !beanName.equals(this.defaultParentBean)) {      parent = this.defaultParentBean;   }   try {      //通过utils工具创建一个GenericBeanDefinition      AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(            parent, className, getBeanClassLoader());      //组装解析到的属性值      bd.setScope(scope);      bd.setAbstract(isAbstract);      bd.setLazyInit(lazyInit);      bd.setConstructorArgumentValues(cas);      bd.setPropertyValues(pvs);      //注册到beanFactory中,这里的registry其实就是DefaultListableBeanFactory,添加到其维护的      //ConcurrentHashMap中      getRegistry().registerBeanDefinition(beanName, bd);   }   catch (ClassNotFoundException ex) {      throw new CannotLoadBeanClassException(resourceDescription, beanName, className, ex);   }   catch (LinkageError err) {      throw new CannotLoadBeanClassException(resourceDescription, beanName, className, err);   }}

第二步 获取bean

//类AbstractBeanFactoryprotected 
 T doGetBean(      final String name, final Class
 requiredType, final Object[] args, boolean typeCheckOnly)      throws BeansException {   final String beanName = transformedBeanName(name);   Object bean;   // 先去缓冲中取   Object sharedInstance = getSingleton(beanName);   if (sharedInstance != null && args == null) {        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);   }else {      // Fail if we're already creating this bean instance:      // We're assumably within a circular reference.      if (isPrototypeCurrentlyInCreation(beanName)) {         throw new BeanCurrentlyInCreationException(beanName);      }      //去父factory获取      BeanFactory parentBeanFactory = getParentBeanFactory();      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {        --------代码省略 具体可去看spring源码-----         return xxxxxx;      }      if (!typeCheckOnly) {         markBeanAsCreated(beanName);      }      try {         //前面提到的RootBeanDefinition 可以用来合并多个definition         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);         checkMergedBeanDefinition(mbd, beanName, args);         // Guarantee initialization of beans that the current bean depends on.         --------代码省略 具体可去看spring源码-----         // Create bean instance.         //单例         if (mbd.isSingleton()) {            //先是去缓冲取,取不到在createBean,这里就不跟进去了层级还很深。主要是创建bean,            //把我们配置的属性值都注入进去 ,然后bean缓冲起来            sharedInstance = getSingleton(beanName, new ObjectFactory
() {               @Override               public Object getObject() throws BeansException {                  try {                     return createBean(beanName, mbd, args);                  }                  catch (BeansException ex) {                    destroySingleton(beanName);                     throw ex;                  }               }            });            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);         }         //原型和单例没有太大的区别,主要是是否缓冲区实例,原型每次都创建新的实例         else if (mbd.isPrototype()) {            // It's a prototype -> create a new instance.            Object prototypeInstance = null;            try {               beforePrototypeCreation(beanName);               prototypeInstance = createBean(beanName, mbd, args);            }            finally {               afterPrototypeCreation(beanName);            }            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);         }         else {            String scopeName = mbd.getScope();            final Scope scope = this.scopes.get(scopeName);            if (scope == null) {               throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");            }            try {               Object scopedInstance = scope.get(beanName, new ObjectFactory() {                  @Override                  public Object getObject() throws BeansException {                     beforePrototypeCreation(beanName);                     try {                        return createBean(beanName, mbd, args);                     }                     finally {                        afterPrototypeCreation(beanName);                     }                  }               });               bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);            }            catch (IllegalStateException ex) {               throw new BeanCreationException(beanName,                     "Scope '" + scopeName + "' is not active for the current thread; consider " +                     "defining a scoped proxy for this bean if you intend to refer to it from a singleton",                     ex);            }         }      }      catch (BeansException ex) {         cleanupAfterBeanCreationFailure(beanName);         throw ex;      }   }  --------代码省略 具体可去看spring源码-----   return (T) bean;}

基本大概从beanFactory获取bean 就是这个过程。

ApplicationContext

类图

182055_ZrMB_223302.png

从ApplicationContext和BeanFactory类图中可以看出它们的顶级接口大部分是相同的,只是ApplicationContext接口更多一些。ApplicationContext的实现类其实是包装了DefaultListableBeanFactory类着一点可以从其代码可以看出

183322_d2AV_223302.png

所有的有关bean的获取等操作都会委托到DefaultListableBeanFactory

183323_R0zC_223302.png

    ApplicationContext多了MessageSource,ApplicationEventPulisher,ResourceLoader等接口。

这里篇幅比较长了,不在详细介绍ApplicationContext接口。

    IOC 容器 对bean的主要操作就是这样。

本文链接

转载于:https://my.oschina.net/robinyao/blog/647509

你可能感兴趣的文章
CentOS 6.3部署KVM虚拟机 V1.0
查看>>
RHCS
查看>>
Tomcat启动脚本catalina.sh
查看>>
Django解决扩展用户表时,后台Admin显示密码为明文的问题
查看>>
vCenter连接ESXi主机出错
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
linux(redhat系)系统启动级别设置
查看>>
Windows Server Version 1709下载地址
查看>>
Kotlin的数据库DSL
查看>>
Docker系列教程14-Docker数据持久化
查看>>
PyTorch快速入门教程九(使用LSTM来做判别每个词的词性)
查看>>
EIGRP非等价负载均衡
查看>>
【linux】【if】判断
查看>>
利用Jmeter向MySQL批量插入数据
查看>>
c++晚捆绑的实现机制
查看>>
C语言:两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同(模除、移位)...
查看>>
学生成绩管理系统及文件结构分析
查看>>
老李推荐:第6章8节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-小结...
查看>>