IOC(一)BeanFactory和BeanDefinition

前言

从这篇文章开始我会去探索一下Spring中IOC机制的一些底层实现,至于IOC(控制反转)是什么在这里不多做介绍,网上的资料也很多。

IOC(控制反转)是Spring框架中最核心的机制,所以我们需要对其实现原理有一定的理解,才能更好的使用它甚至自己设计一个类似Spring的简单框架。这篇文章我们先不管其运行流程,而是先来看一下他的两个重要的接口,只有先把这些接口弄明白了,我们才能理解IOC机制的工作流程及原理。

BeanFactory

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;

public interface BeanFactory {

    String FACTORY_BEAN_PREFIX = "&";
    
    Object getBean(String name) throws BeansException;

     T getBean(String name, Class requiredType) throws BeansException;

     T getBean(Class requiredType) throws BeansException;

    Object getBean(String name, Object... args) throws BeansException;

    boolean containsBean(String name);

    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException;
    
    Class getType(String name) throws NoSuchBeanDefinitionException;

    String[] getAliases(String name);
}复制代码
这个便是spring核心的Bean工厂定义,上面的author说是2001年写的,已经历史久远了, 这个类是spring中所有bean工厂,也就是俗称的IOC容器的祖宗,各种IOC容器都只是它的实现或者为了满足特别需求的扩展实现。 从上面的方法就可以看出,这些工厂的实现最大的作用就是根据bean的名称亦或类型等等,来返回一个bean的实例。

BeanFactory
  BeanFactory,以Factory结尾,表示它是一个工厂类(接口), 它负责生产和管理bean的一个工厂。在Spring中, BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

       BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,其中XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。XmlBeanFactory类将持有此XML配置元数据,并用它来构建一个完全可配置的系统或应用。

ApplicationContext接口

它由BeanFactory接口派生而来,ApplicationContext包含BeanFactory的所有功能,通常建议比BeanFactory优先。

ApplicationContext以一种更向面向框架的方式工作以及对上下文进行分层和实现继承,ApplicationContext包还提供了以下的功能:

  • MessageSource, 提供国际化的消息访问
  • 资源访问,如URL和文件
  • 事件传播
  • 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层;

对BeanFactory的思考

一个工厂如果想拥有这样的功能,那么它一定需要以下几个因素:
  1. 需要持有各种bean的定义,否则无法正确的完成bean的实例化。
  2. 需要持有bean之间的依赖关系,否则在bean实例化的过程中也会出现问题。例如,A包含了B的实例。但是在A初始化之后,调用B实例的方法时,就会报空指针异常,因为A并没有被真正的正确初始化。
  3. 以上两种都要依赖于我们所写的依赖关系的定义,暂且认为是XML文件(其实可以是各种各样的),那么我们需要一个工具来完成XML文件的读取。

我目前想到的,只需要满足以上三种条件,便可以创建一个bean工厂,来生产各种bean。当然,spring肯定有更高级的做法,以上只是我直观的去想如何实现IOC。

那么从上面的描述中,我又引申出了另一个核心问题,Bean的定义是什么,他的依赖关系又如何描述?

那么答案是,一个祖宗级别的接口,来看BeanDefinition。

BeanDefinition

package org.springframework.beans.factory.config;

import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.AttributeAccessor;

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

    int ROLE_APPLICATION = 0;

    int ROLE_SUPPORT = 1;

    int ROLE_INFRASTRUCTURE = 2;

    String getParentName();

    void setParentName(String parentName);

    String getBeanClassName();

    void setBeanClassName(String beanClassName);

    String getFactoryBeanName();

    void setFactoryBeanName(String factoryBeanName);

    String getFactoryMethodName();

    void setFactoryMethodName(String factoryMethodName);

    String getScope();

    void setScope(String scope);

    boolean isLazyInit();

    void setLazyInit(boolean lazyInit);

    String[] getDependsOn();

    void setDependsOn(String[] dependsOn);

    boolean isAutowireCandidate();

    void setAutowireCandidate(boolean autowireCandidate);
    
    boolean isPrimary();

    void setPrimary(boolean primary);

    ConstructorArgumentValues getConstructorArgumentValues();

    MutablePropertyValues getPropertyValues();

    boolean isSingleton();

    boolean isPrototype();

    boolean isAbstract();

    int getRole();

    String getDescription();

    String getResourceDescription();

    BeanDefinition getOriginatingBeanDefinition();
}复制代码
接口上给出的注释简明扼要的描述了该接口: BeanDefinition描述了一个bean实例,它具有属性值,构造函数参数值以及具体实现提供的更多信息。

可以看到上面的很多属性和方法都很熟悉,例如类名、scope、属性、构造函数参数列表、依赖的bean、是否是单例类、是否是懒加载等,其实就是将Bean的定义信息存储到这个BeanDefinition相应的属性中,后面对Bean的操作就直接对BeanDefinition进行,例如拿到这个BeanDefinition后,可以根据里面的类名、构造函数、构造函数参数,使用反射进行对象创建。 BeanDefinition是一个接口,是一个抽象的定义,实际使用的是其实现类,如ChildBeanDefinition、RootBeanDefinition、GenericBeanDefinition等。

继承关系

BeanDefinition这个接口便是spring中的bean定义接口,所以其实我们工厂里持有的bean定义,就是一堆这个玩意,或者是他的实现类和子接口。这个接口并非直接的祖宗接口,他所继承的两个接口一个是core下面的AttributeAccessor,继承这个接口就以为这我们的bean定义接口同样具有处理属性的能力,而另外一个是beans下面的BeanMetadataElement,这个接口就是bean的元数据元素,它可以获得bean的配置定义的一个元素。在XML文件中来说,就是会持有一个bean标签。


BeanDefinition的一些依赖与实现,这里就不细致展开
(图片参考自 www.jianshu.com/p/1d06f6342…

小结

本篇文章介绍了Spring实现IOC这一机制的最基础的两个接口BeanFactory和BeanDefinition。一个是生产Bean的工厂,一个是对Bean的定义,这两个接口以最基础的形式定义了Bean是什么以及是如何产生的,Spring在实际应用中使用的类或者接口很多也都是实现了这两个接口,如ApplicationContext、ChildBeanDefinition等等。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值