深入学习 Spring Web 开发 —— BeanDefinition(上)

CodeRover
• 阅读 475

本文主要探讨什么是 BeanDefinition,下一篇文章,我们将探讨 BeanDefinition 是如何起作用的。

BeanDefinition 是什么

下面,我们先看一下 BeanDefinition 的源码:

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;

    void setParentName(@Nullable String parentName);

    @Nullable
    String getParentName();

    void setBeanClassName(@Nullable String beanClassName);

    @Nullable
    String getBeanClassName();

    void setScope(@Nullable String scope);

    @Nullable
    String getScope();

    void setLazyInit(boolean lazyInit);

    boolean isLazyInit();

    void setDependsOn(@Nullable String... dependsOn);

    @Nullable
    String[] getDependsOn();

    void setAutowireCandidate(boolean autowireCandidate);

    boolean isAutowireCandidate();

    void setPrimary(boolean primary);

    boolean isPrimary();

    void setFactoryBeanName(@Nullable String factoryBeanName);

    @Nullable
    String getFactoryBeanName();

    void setFactoryMethodName(@Nullable String factoryMethodName);

    @Nullable
    String getFactoryMethodName();

    ConstructorArgumentValues getConstructorArgumentValues();

    default boolean hasConstructorArgumentValues() {
        return !getConstructorArgumentValues().isEmpty();
    }

    MutablePropertyValues getPropertyValues();

    default boolean hasPropertyValues() {
        return !getPropertyValues().isEmpty();
    }

    void setInitMethodName(@Nullable String initMethodName);

    @Nullable
    String getInitMethodName();

    void setDestroyMethodName(@Nullable String destroyMethodName);

    @Nullable
    String getDestroyMethodName();

    void setRole(int role);

    int getRole();

    void setDescription(@Nullable String description);

    @Nullable
    String getDescription();

    ResolvableType getResolvableType();

    boolean isSingleton();

    boolean isPrototype();

    boolean isAbstract();

    @Nullable
    String getResourceDescription();

    @Nullable
    BeanDefinition getOriginatingBeanDefinition();

}

可以看到 BeanDefinition 是一个接口,它继承了 AttributeAccessor 和 BeanMetadataElement,其中 AttributeAccessor 的源码如下:

public interface AttributeAccessor {

    void setAttribute(String name, @Nullable Object value);

    @Nullable
    Object getAttribute(String name);

    @SuppressWarnings("unchecked")
    default <T> T computeAttribute(String name, Function<String, T> computeFunction) {
        Assert.notNull(name, "Name must not be null");
        Assert.notNull(computeFunction, "Compute function must not be null");
        Object value = getAttribute(name);
        if (value == null) {
            value = computeFunction.apply(name);
            Assert.state(value != null,
                    () -> String.format("Compute function must not return null for attribute named '%s'", name));
            setAttribute(name, value);
        }
        return (T) value;
    }

    @Nullable
    Object removeAttribute(String name);

    boolean hasAttribute(String name);

    String[] attributeNames();

}

AttributeAccessor 主要提供了访问和修改属性的方法。

需要注意的是,这里的属性是额外加给 BeanDefinition 的属性,而不是它所代表的对象本身的属性。

BeanMetadataElement 的源码如下:

public interface BeanMetadataElement {

    @Nullable
    default Object getSource() {
        return null;
    }

}

BeanMetadataElement 只提供了一个方法,它是用来获取 Bean 元数据的配置源的(一般指向 Bean 对象的 class 文件的磁盘目录)。

了解完这两个接口,我们再看回到 BeanDefinition 的源码,其中包含了几个静态变量:

    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

    int ROLE_APPLICATION = 0;
    int ROLE_SUPPORT = 1;
    int ROLE_INFRASTRUCTURE = 2;

SCOPE_SINGLETON、SCOPE_PROTOTYPE 用于表示对象是单例还是多例的,ROLE_ 开头的几个常量跟 ComponentDefinition 有关,具体的作用在此不做分析,有兴趣的读者可以自行研究。

接下来,我们可以看到下面的方法,这些方法跟我们如何定义这个 BeanDefinition 有关,我们前面讲到的用来定义 Bean 特性的一些内容,如:@Scope、@Lazy、@DependsOn、@Primary、initMethod、destroyMethod、是否是候选类等,在这里都可以看到。

    void setScope(@Nullable String scope);

    @Nullable
    String getScope();

    void setLazyInit(boolean lazyInit);

    boolean isLazyInit();

    void setDependsOn(@Nullable String... dependsOn);

    @Nullable
    String[] getDependsOn();

    void setAutowireCandidate(boolean autowireCandidate);

    boolean isAutowireCandidate();

    void setPrimary(boolean primary);

    boolean isPrimary();

    void setInitMethodName(@Nullable String initMethodName);

    @Nullable
    String getInitMethodName();

    void setDestroyMethodName(@Nullable String destroyMethodName);

    @Nullable
    String getDestroyMethodName();

    boolean isSingleton();

    boolean isPrototype();

再接着,我们看到下面的方法,基本上是一些辅助性方法和对 Bean 对象本身的基本内容进行管理的方法(如:对类名、构造函数参数值、属性值等进行管理的方法)。

    void setParentName(@Nullable String parentName);

    @Nullable
    String getParentName();

    void setBeanClassName(@Nullable String beanClassName);

    @Nullable
    String getBeanClassName();

    void setFactoryBeanName(@Nullable String factoryBeanName);

    @Nullable
    String getFactoryBeanName();

    void setFactoryMethodName(@Nullable String factoryMethodName);

    @Nullable
    String getFactoryMethodName();

    ConstructorArgumentValues getConstructorArgumentValues();

    default boolean hasConstructorArgumentValues() {
        return !getConstructorArgumentValues().isEmpty();
    }

    MutablePropertyValues getPropertyValues();

    default boolean hasPropertyValues() {
        return !getPropertyValues().isEmpty();
    }

    void setDescription(@Nullable String description);

    @Nullable
    String getDescription();

    void setRole(int role);

    int getRole();

    ResolvableType getResolvableType();

    boolean isAbstract();

    @Nullable
    String getResourceDescription();

    @Nullable
    BeanDefinition getOriginatingBeanDefinition();

总结

本文,我们简单介绍了 BeanDefinition 的基本内容,下一篇文章,我们将探讨它是如何起作用的。

点赞
收藏
评论区
推荐文章
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Easter79 Easter79
4年前
spring源码解析
前言上篇我们介绍了spring容器加载的方式,并重点介绍了基于xml配置解析和注解扫描两种容器加载的方式,封装和注册beandefinition的过程。今天我们分享BeanDefinition注册后的另一个重要过程bean的实例化过程的源码。容器加载流程!spring源码解析spring容器加载源码(bean实
Stella981 Stella981
4年前
BeanDefinition 合并
BeanDefinition的合并1.BeanDefinition有父子关系,有个属性叫parentName,通过parentName可以设置BeanDefinition的父子关系2.为什么要设置BeanDefinition的父子关系,因为子类可以继承父类的属性,抽出共性,跟java的继承有点像3.Be
Easter79 Easter79
4年前
Springboot浅析(三)——容器刷新流程
一、先了解下各种后置处理器扩展点(一)BeanFactoryPostProcessor——bean工厂后置处理BeanFactory标准初始化完毕后(经过包扫描后所有的BeanDefinition已经被注册),可以对这个Bea
Stella981 Stella981
4年前
Spring 源码第四弹!深入理解 BeanDefinition
松哥原创的SpringBoot视频教程已经杀青,感兴趣的小伙伴戳这里SpringBootVue微人事视频教程(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI1NDY0MTkzNQ%3D%3D%26mi
Stella981 Stella981
4年前
Spring IOC 之 注册 BeanDefinition
获取Document对象后,会根据该对象和Resource资源对象调用 registerBeanDefinitions() 方法,开始注册BeanDefinitions!(https://oscimg.oschina.net/oscnet/36e85103bf03cfbc0117fc33eb4af909c0a.jpg)首先调
Easter79 Easter79
4年前
Spring对configuration class的加载
前言本文不讲解源码,仅记录加载过程中的一部分。看本文需要先知道spring对BeanDefinition的处理,对bean的实例化。单元测试和配置publicclassConfig{}publicclassContextLoadTest{privateA
Easter79 Easter79
4年前
Spring源码解析(三)BeanDefinition的载入、解析和注册
  通过上一篇源码的分析已经完成了BeanDefinition资源文件的定位,本篇继续分析BeanDefinition资源文件的载入和解析。AbstractBeanDefinitionReader的loadBeanDefinitions(Stringlocation,Set<ResouceactualResouces)方法完成定位,紧接着调用loa
带着问题去分析:Spring Bean 生命周期 | 京东物流技术团队
1:Bean在Spring容器中是如何存储和定义的Bean在Spring中的定义是org.springframework.beans.factory.config.BeanDefinition接口,BeanDefinition里面存储的就是我们编写的Jav
liam liam
2年前
Python aiohttp 异步请求处理最佳实践
aiohttp就是中一款优秀的异步Web框架,它能够帮助我们构建高效的异步Web应用和异步HTTP客户端。在本文中,我们将深入探讨aiohttp是什么以及如何使用它,通过简单易懂的案例带领你理解异步编程,以及如何处理异步请求和异步HTTP客户端。什么是ai