spring源代码分析(3):关于BeanDefinition的思考

来源:互联网 发布:用友u8数据备份计划 编辑:程序博客网 时间:2024/06/06 20:58
我们这一节重点来看看Spring的BeanDefinition的结构,我是一个刚从事软件开发工作的学生,这也只是我个人阅读源码的一些笔记和收获,如果有朋友看见了这些笔记,虚心求教,但请不要肆意攻击,指出错误感激不尽;

spring2.0的源码中的BeanDefinition的结构类图和上一节有所不同;如下:




从类图中,我们可以看见AbstractBeanDefinition虽然没有Abstract方法,但是依旧声明了Abstract类,那是因为在整个系统中,他在认知中不可能实例化一个具体的类,那我们就要在设计阶段将他给限定下来;

最后在系统我们可以生成的类,就只有两种,分别是
RootBeanDefinition:对应于Xml文件中的一个顶级的(即没有Parent)的Bean定义;

ChildBeanDefinition:对应于一个子Bean定义,他是从一个已有的Bean继承而来;

    public ChildBeanDefinition(String parentName) {
        super();
        this.parentName = parentName;
    }


    public ChildBeanDefinition(String parentName, MutablePropertyValues pvs) {
        super(null, pvs);
        this.parentName = parentName;
    }

  
    public ChildBeanDefinition(
            String parentName, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {

        super(cargs, pvs);
        this.parentName = parentName;
    }

   
    public ChildBeanDefinition(
            String parentName, Class beanClass, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {

        super(cargs, pvs);
        this.parentName = parentName;
        setBeanClass(beanClass);
    }

  
    public ChildBeanDefinition(
            String parentName, String beanClassName, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {

        super(cargs, pvs);
        this.parentName = parentName;
        setBeanClassName(beanClassName);
    }

  
    public String getParentName() {
        return parentName;
    }
在这里有对父Bean的访问和联系;

AttributeAccessor是一个对属性进行修改,增加,删除功能的接口,在AccessorSupport中,我们维护一个Map类型的属性作为属性的容器;

在查看了源码以后,提出几点疑问并且尝试自己解答:

(1):
BeanDefinition继承了两个接口,实现了多继承,为什么我们不能采用一下类图结构来达到Accessor和BeanMetadataSource功能的组合:


答:这是因为我们在划分接口的时候,以最小的功能位细粒度,所以在这里我们抽取出来两个接口,但是在功能进行组合的时候,我们的接口采用继承还是“集成”,首先取决与分类学的角度来看待问题,两者之间是否是平行关系还是“副词/形容词”修饰的关系;比如说在BeanFactory中有

HierarchicalBeanFactory继承于BeanFactory接口,那么,我们把HierarchicalBeanFactory看成是
“拥有等级功能”  的  “Bean工厂”

这就是修饰的概念,系统中没有一个叫做“等级功能”的单独的接口体系,他是对BeanFactory的进一步细化;

然而,在系统中,我们存在一个叫做"属性访问器"和"Bean元信息元素"的接口,属性访问是一个角色,是名词,代码一组
实际存在的功能对象的共性,如PropertyValues类。在这里,若AttributeAccessor继承BeanMetadataElement,那么就造成了接口污染,我们无法单独继承和实现AttributeAccessor;所以在这里我们选择BeanDefinition分别具有两种接口;




(2):在实现AbstractBeanDefinition的时候,我们继承了BeanDefinition接口,就表示我们间接的实现了AttributeAccessor
接口,为什么我们还要抽象出一个AbstractAccessorSupport来,并且继承这个抽象类呢?这不会是一种重复继承吗?

答:这是为了达到复用的目的,这个问题我们从重构的角度比较好分析;
在重构一书中,我们可以清晰的看到,如果两个类中间的代码有大多数相同,那么我们应该尝试把这些代码抽取出来成为一个类,然后继承于他;

由于PropertyValues中和AbstractBeandefinition中有关AttributeAccessor的代码都是相同的,所以我们有理由他这部分抽取出来成为一个抽象类(不能实例化,仅仅提供代码的复用),在这里,不存在重复继承因为代码复用的手段一种是集成,一种是继承,在这里,因为他们有共同的一个实现接口,所以采用继承的手段来达到复用;

(3):我们可以看到在childBeanFactory的代码中有getParentName方法是在接口BeanDefinition中不存在的,而在AbstractBeanFactory中的getMegerDefinition中,我们频繁的出现类BeanDefinition代码的instanceOf 类型判断来调用
getParentName方法,在这里,我们可不可以在BeanDefinition中实现这个方法,并且在RootBeanDefinition中空实现这个方法,利用多状来进行类型判断;

答:不好,因为空实现不代表不具有这个功能,接口只所以抽象出来是因为他代表了实现这个接口的类的共性,既然有类不具有这种功能,那么我们就不应该把他放在接口的定义里面,这只能说明拥有这中功能的类,是这个顶层接口的扩展和特例,那么我们可以采取这种手段来实现:


这里,由于我们ChildBeanDefinition只有一个唯一的实现,并且以后扩展的可能性也很小,所以我们并不一定要拿出一个抽象的接口层:IChildbeanDefinition而直接得到ChildBeanDefinition;(找出变化和扩展点,抽象他)


原创粉丝点击