zoukankan      html  css  js  c++  java
  • Spring学习系列(三)——BeanFactory的三类实现DefaultListableBeanFactory,StaticListableBeanFactory,SimpleJndiBeanFactory.

    1.Java中创建对象的几种方式

    Java作为面向对象语言的一种,有种说法是万物皆对象。我们的应用程序也是由一个个类或对象组成的,可以说对象是Java的灵魂。

    对象并不会凭空出现,那么对象是怎么来的?你可能会说对象是new出来的,当然通多new调用构造器能够创建对象,那么是否有其他创建对象的方式呢?

    答案肯定的,接下来简单介绍几种创建对象的方式(综合网络中的众多结果简单介绍,不做深入描述)

    常说的五种创建对象的方式

    1. new创建,通过new关键字调用构造方法
    2. 反射创建对象,Class中的newInstance()方法和Constructor中的newInstance(),注意区分两者的区别。
    3. Object中的clone方法创建,记得实现Cloneable接口
    4. 反序列化创建,首先要有列化之后的对象资源,实现Serializable接口
    5. Unsafe.getUnsafe().allocateInstance(Class.class)  rt.jar中sun.misc包中的native方法。

    另外还有几种特殊的创建方式

    1. jdk动态代理  java.lang.reflect.Proxy
    2. cglib代理创建 
    3. Objenesis类库 提供了多种创建对象的方式

    上面列出了目前能用到的创建对象的几乎所有方式(如果还有其他的方式,基本原理应该也会与上面的类似)。

    小结:Spring作为IOC容器,功能就是反转创建对象的控制权。所以了解创建对象的方式还是很有必要。具体Spring采用哪种方式创建对象,后续揭秘(当然是因为还没看到,哈哈)。

    2.Java中的反射和内省

    a. 先简单说一下反射

    核心是构造Class(对任何对象的类的抽象描述),通过Class类的对象我们可以获取关于类更加细节的描述信息,如Constructor,Method,Field等。

    这里说明一下Class中的newInstance方法,返回tmpConstructor.newInstance((Object[])null);可以看出调用Constructor中的无参构造器。

    而Constructor中的newInstance方法,则调用的是ConstructorAccessor(package sun.reflect)接口定义的newInstance方法,

    这些ConstructorAccessor实现中的newInstance方法:分两种

    一种是NativeConstrutorAccessorImpl中的

    一种是Unsafe中的

    而newInstance方法实际调用了第一种实现,第二种Unsafe具体在什么情景下使用不再深究。

    b.简单说一下内省

    内省机制相关的主要的类或接口有:Introspector(用来操作BeanInfo),BeanInfo(定义了获取有关Bean信息的方法,bean,method,property,even等),FeatureDescriptor。

    jdk提供了一个BeanInfo接口的简单实现SimpleBeanInfo,而查看源码我们发现SimpleBeanInfo并没有具体的操作,可以参考SimpleBeanInfo的一个子类Introspector.GenericBeanInfo。

    可以看出内省机制的核心就是Introspector(内省),接下来简单介绍一下Introspector。

    getBeanInfo()是Introspector的核心,用来获取bean,method,event,property对应的FeatureDescriptor子类,并构造出GenericBeanInfo。

    其中bean和method的相对直观,重点看一下EventSetDescriptor esds[] = getTargetEventInfo();和 PropertyDescriptor pds[] = getTargetPropertyInfo();

    简单来说,两者都是通过method实现的,

    ①在事件中通过add和remove前缀及Listener后缀,将一个方法约定为一个事件。

    ②在属性中通过get和set(boolean类型的is)作为前缀,构造PropertyDescriptor。

    这就是为什么说内省是javabean的一种缺省表达。Class中只要有get,set方法,即使没有对应的属性,内省机制也会认为有一个属性(构造PropertyDescriptor)。

    小结:内省机制是基于反射的,许多框架都使用了内省机制。内省机制可以让我们更多的关注方法,而不用过多的关注属性(这在面向接口编程的时候非常有用)。

    3.Spring中的BeanFactory体系

    程序设计是自顶向下的一个过程,而程序开发是自底向上的过程(研究源码也是如此)。

    例如现在我们知道Spring的核心之一是BeanFactory,那么如何由BeanFactory(顶层接口)去分析BeanFactory体系的方法,应该是自底而上的通过具体的实现去了解分析整个体系。

    可能我们通过一些资料也有所了解BeanFactory的底层实现是DefaultListableBeanFactory.而我们研究源码的首要问题是,我们如何去定位这个底层实现。

    简单来说就是如何确定BeanFactory的实现,目前我所了解的方式就是通过查看API文档。如下所示

    以前总结的学习源码的心得还是很有用的(查,看,跑,造,比,买)。在看源码之前一定要先查API。看看官方对一些概念知识的解释(网上的有些描述不太准确)是很有必要的。

    从BeanFactory的介绍中我们看到,后续还要了解bean的定义和生命周期相关的知识。

    结合上图我们可以清晰的看到BeanFactory的一些实现类(接口和ApplicationContext相关的后续研究)。

    这里我们通过API定位出BeanFactory的三类实现:XmlBeanFactory,StaticListableBeanFactory,SimpleJndiBeanFactory.

    a.StaticListableBeanFactory

     

    查看StaticListableBeanFactory源码,我们知道这是一个基于 LinkedHashMap<String, Object>()的ListableBeanFactory单例实现,不支持原型模式和别名。

    b.SimpleJndiBeanFactory

     

    查看SimpleJndiBeanFactory源码,是基于JndiLocatorSupport的BeanFactory实现,并使用HashMap进行缓存处理。

    这里需要注意,SimpleJndiBeanFactory不支持枚举的bean定义,因此没有实现ListableBeanFactory,而是直接实现的BeanFactory。

    c.XmlBeanFactory/DefaultListableBeanFactory

    接下来重点聊聊XmlBeanFactory系列(尽管XmlBeanFactory已经弃用了,作为学习研究还是很有必要的)。

    c1. XmlBeanFactory是一个由XmlBeanDefinitionReader加载bean定义的DefaultListableBeanFactory。

    c2. DefaultListableBeanFactory是一个基于bean定义的比较完善的bean工厂,是ListableBeanFactory和BeanDefinitionRegistry的默认实现。

    在学习DefaultListableBeanFactory时,我们需要关注类中涉及到的BeanDefinition接口(描述bean的属性,构造参数和其他数据,接口中定义了scope和role)

    ,RootBeanDefinition类(更多的使用GenericBeanDefinition),AutowireCandidateResolver。

    以下简单介绍DefaultListableBeanFactory系列的接口

    c3. ConfigurableListableBeanFactory

    此接口综合了ListableBeanFactory,AutowireCapableBeanFactory,ConfigurableBeanFactory并在此基础上扩展了对bean definitions的分析修改,以及预实例化单例bean的功能。

    其中ListableBeanFactory是一种可以把所有bean列举出来的BeanFactory(而不是查找出一个结果)

    AutowireCapableBeanFactory是一种可以对bean进行管理的BeanFactory,扩展了自动装配的功能。

    ConfigurableBeanFactory是一个巨大的接口,继承了HierarchicalBeanFactory和SingletonBeanRegistry,并定义了许多bean相关的细节。

    其他具体的实现类会在后续博文中介绍,当然相关的接口也会详细介绍。这里只是对BeanFactory体系作简单的介绍。

    小结:我们可以看到,在BeanFactory的三类实现中:StaticListableBeanFactory和SimpleJndiBeanFactory相对简单稍作了解即可,DefaultListableBeanFactory是三个中最重要,最常用,也是最复杂的一种,后续会详细介绍。

    4.总结

    首先介绍了对象的创建,并在源码层面简单介绍了java的反射和内省机制(后续会用到这部分知识),而后基于BeanFactoryAPI自顶向下深挖实现,并以自底向上的方式分析BeanFactory体系。

    本想着用一片文章介绍BeanFactory体系,但深入研究后发现这个体系有些庞大的过分,只能拆作几个部分介绍。

    当然依然是按照本文的这种自底向上的分析方法:重点介绍DefaultListableBeanFactory核心分支体系中各个接口和实现。

  • 相关阅读:
    转载: RAID详解[RAID0/RAID1/RAID10/RAID5]
    用户交互式命令:read
    linux下fdisk分区管理、文件系统管理、挂载文件系统等
    linux文件系统下的特殊权限
    find命令详解
    python3中 getpass模块使用
    个人shell积累
    手把手教你利用爬虫爬网页(Python代码)
    数通HCIP-ospf知识点
    HCIE之路--超全ospf思维导图
  • 原文地址:https://www.cnblogs.com/masting/p/11371760.html
Copyright © 2011-2022 走看看