专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

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标签。

51_1.png

BeanDefinition的一些依赖与实现,这里就不细致展开

(图片参考自 www.jianshu.com/p/1d06f6342…

小结

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

文章永久链接:https://tech.souyunku.com/41197

未经允许不得转载:搜云库技术团队 » IOC(一)BeanFactory和BeanDefinition

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们