第五十九章 Spring之假如让你来写Boot——番外篇:再谈Bean定义

Spring源码阅读目录

第一部分——IOC篇

第一章 Spring之最熟悉的陌生人——IOC
第二章 Spring之假如让你来写IOC容器——加载资源篇
第三章 Spring之假如让你来写IOC容器——解析配置文件篇
第四章 Spring之假如让你来写IOC容器——XML配置文件篇
第五章 Spring之假如让你来写IOC容器——BeanFactory和FactoryBean
第六章 Spring之假如让你来写IOC容器——Scope和属性填充
第七章 Spring之假如让你来写IOC容器——属性填充特别篇:SpEL表达式
第八章 Spring之假如让你来写IOC容器——拓展篇
第九章 Spring之源码阅读——环境搭建篇
第十章 Spring之源码阅读——IOC篇

第二部分——AOP篇

第十一章 Spring之不太熟的熟人——AOP
第十二章 Spring之不得不了解的内容——概念篇
第十三章 Spring之假如让你来写AOP——AOP联盟篇
第十四章 Spring之假如让你来写AOP——雏形篇
第十五章 Spring之假如让你来写AOP——Joinpoint(连接点)篇
第十六章 Spring之假如让你来写AOP——Pointcut(切点)篇
第十七章 Spring之假如让你来写AOP——Advice(通知)上篇
第十八章 Spring之假如让你来写AOP——Advice(通知)下篇
第十九章 Spring之假如让你来写AOP——番外篇:Spring早期设计
第二十章 Spring之假如让你来写AOP——Aspect(切面)篇
第二十一章 Spring之假如让你来写AOP——Weaver(织入器)篇
第二十二章 Spring之假如让你来写AOP——Target Object(目标对象)篇
第二十三章 Spring之假如让你来写AOP——融入IOC容器篇
第二十四章 Spring之源码阅读——AOP篇

第三部分——事务篇

第二十五章 Spring之曾经的老朋友——事务
第二十六章 Spring之假如让你来写事务——初稿篇
第二十七章 Spring之假如让你来写事务——铁三角篇
第二十八章 Spring之假如让你来写事务——属性篇
第二十九章 Spring之假如让你来写事务——状态篇
第三十章 Spring之假如让你来写事务——管理篇
第三十一章 Spring之假如让你来写事务——融入IOC容器篇
第三十二章 Spring之源码阅读——事务篇

第四部分——MVC篇

第三十三章 Spring之梦开始的地方——MVC
第三十四章 Spring之假如让你来写MVC——草图篇
第三十五章 Spring之假如让你来写MVC——映射器篇
第三十六章 Spring之假如让你来写MVC——拦截器篇
第三十七章 Spring之假如让你来写MVC——控制器篇
第三十八章 Spring之假如让你来写MVC——适配器篇
第三十九章 Spring之假如让你来写MVC——番外篇:类型转换
第四十章 Spring之假如让你来写MVC——ModelAndView篇
第四十一章 Spring之假如让你来写MVC——番外篇:数据绑定
第四十二章 Spring之假如让你来写MVC——视图篇
第四十三章 Spring之假如让你来写MVC——上传文件篇
第四十四章 Spring之假如让你来写MVC——异常处理器篇
第四十五章 Spring之假如让你来写MVC——国际化篇
第四十六章 Spring之假如让你来写MVC——主题解析器篇
第四十七章 Spring之假如让你来写MVC——闪存管理器篇
第四十八章 Spring之假如让你来写MVC——请求映射视图篇
第四十九章 Spring之假如让你来写MVC——番外篇:属性操作
第五十章 Spring之假如让你来写MVC——融入IOC容器篇
第五十一章 Spring之源码阅读——MVC篇

第五部分——Boot篇

第五十二章 Spring之再进一步——Boot
第五十三章 Spring之假如让你来写Boot——环境篇
第五十四章 Spring之假如让你来写Boot——注解篇(上)
第五十五章 Spring之假如让你来写Boot——注解篇(下)
第五十六章 Spring之假如让你来写Boot——SPI篇
第五十七章 Spring之假如让你来写Boot——配置文件篇(上)
第五十八章 Spring之假如让你来写Boot——配置文件篇(下)
第五十九章 Spring之假如让你来写Boot——番外篇:再谈Bean定义
第六十章 Spring之假如让你来写Boot——自动装配篇
第六十一章 Spring之假如让你来写Boot——番外篇:杂谈Starter
第六十二章 Spring之假如让你来写Boot——番外篇:重构BeanFactory
第六十三章 Spring之假如让你来写Boot——番外篇:再谈ApplicationContext
第六十四章 Spring之假如让你来写Boot——内嵌Web容器篇
第六十五章 Spring之假如让你来写Boot——Main方法启动篇
第六十六章 Spring之最终章——结语篇



前言

    对于Spring一直都是既熟悉又陌生,说对它熟悉吧,平时用用没啥问题,但面试的时候被问的一脸懵逼,就很尴尬,都不好意思在简历上写着熟悉Spring了
在这里插入图片描述

    所以决定花点时间研究研究Spring的源码。主要参考的书籍是:《Spring源码深度解析(第2版)》、《Spring揭秘》、《Spring技术内幕:深入解析Spring架构与设计原理(第2版)》


     书接上回,在上篇 第五十八章 Spring之假如让你来写Boot——配置文件篇(下) 中,A君 已经支持了Yaml配置文件。接下来看看 A君 会有什么骚操作吧

尝试动手写IOC容器

    出场人物:A君(苦逼的开发)、老大(项目经理)

    背景:老大 要求 A君在一周内开发个简单的 IOC容器

    前情提要:A君 已经支持了Yaml配置文件。。。

四十八版 Bean定义

    按照次第顺序,本来这篇需要开始讲核心的功能——自动装配。不过瞅了半天,发现还有一些东西没有准备好,这篇就先来说说——Bean定义

   在之前的版本中,A君 图省事,直接定义了一个BeanDefinition类,用以包装整个Bean信息,但是呢,这其实不符合设计的要求的,毕竟Bean信息可以来源于多个地方,像:xml、注解、还可以是系统内部生成的,这明显又是有多种实现了,一个简单的类不足以表述他们之间的不同点。所以,今天 A君 准备着手改造这部分内容。让其变成符合设计的亚子

Bean来源

    既然说到Bean可以经过不同的来源得到,那么来源就需要抽象成接口了。A君 新增BeanMetadataElement接口,代码如下:

/**
 * 获取Bean来源
 */
public interface BeanMetadataElement {

    default Object getSource() {
        return null;
    }

}

Bean定义

    Bean来源的接口已经定义好了,接下来Bean定义的接口,不过说是接口其实也就一堆get/set方法,Bean的属性就是用来封装信息的,故而其接口也不会太难。新增BeanDefinition接口,代码如下:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    /**
     * 单例
     */
    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
    /**
     * 多利
     */
    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

    /**
     * 表示该 Bean 是应用程序的主要组成部分,通常对应用户自定义的 Bean
     */
    int ROLE_APPLICATION = 0;
    /**
     * 表示该 Bean 是某个更大配置的支持部分,通常是外部 ComponentDefinition 的一部分
     */
    int ROLE_SUPPORT = 1;
    /**
     * 表示该 Bean 提供完全的后台角色,对最终用户无关紧要。用于注册完全属于内部工作的 Bean
     */
    int ROLE_INFRASTRUCTURE = 2;

    /**
     * 获取父类
     *
     * @return
     */
    String getParentName();

    void setParentName(String parentName);

    /**
     * 获取bean对应的class全路径
     *
     * @return
     */
    String getBeanClassName();

    void setBeanClassName(String beanClassName);

    /**
     * 获取作用域
     *
     * @return
     */
    String getScope();

    void setScope(String scope);

    /**
     * 是否懒加载
     *
     * @return
     */
    boolean isLazyInit();

    String[] getDependsOn();

    void setDependsOn(String... dependsOn);

    /**
     * 是否自动注入
     *
     * @return
     */
    boolean isAutowireCandidate();

    void setAutowireCandidate(boolean autowireCandidate);

    /**
     * 是否默认bean
     *
     * @return
     */
    boolean isPrimary();

    void setFactoryMethodName(String factoryMethodName);

    /**
     * 获取初始化方法名
     *
     * @return
     */
    String getInitMethodName();
	//省略其他代码。。。
}

这接口实在没啥好说的,接下来就是抽象类了。其实基本上也差不多,一堆的属性,加上get/set。新增AbstractBeanDefinition类,代码如下:

public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
        implements BeanDefinition, Cloneable {

    public static final String SCOPE_DEFAULT = "";

    public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;

    public static final int DEPENDENCY_CHECK_NONE = 0;

    public static final int DEPENDENCY_CHECK_OBJECTS = 1;

    public static final int DEPENDENCY_CHECK_SIMPLE = 2;
    public static final int DEPENDENCY_CHECK_ALL = 3;

    public static final String INFER_METHOD = "(inferred)";
    private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>();

    private volatile Object beanClass;
    private String id;
    private String scope = SCOPE_DEFAULT;
    private boolean abstractFlag = false;

    private Boolean lazyInit;
    private int autowireMode = AUTOWIRE_NO;
    private int dependencyCheck = DEPENDENCY_CHECK_NONE;

    private String[] dependsOn;
    private boolean autowireCandidate = true;
    private boolean primary = false;


    protected AbstractBeanDefinition(ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
        this.constructorArgumentValues = cargs;
        this.propertyValues = pvs;
    }

    @Override
    public String getBeanClassName() {
        Object beanClassObject = this.beanClass;
        if (beanClassObject instanceof Class) {
            return ((Class<?>) beanClassObject).getName();
        } else {
            return (String) beanClassObject;
        }
    }

    @Override
    public void setBeanClassName(String beanClassName) {
        this.beanClass = beanClassName;
    }
    //省略其他方法。。。
}

接下来就是真正的细分了,先来看下最为通用的Bean定义,它只有一个层级结构。新增GenericBeanDefinition类,代码如下:

/**
 * 既可以独立使用,也可以通过设置 parentName 属性来实现继承关系,灵活性更高
 */
public class GenericBeanDefinition extends AbstractBeanDefinition {

    /**
     * 父类bean
     */
    private String parentName;

    //省略其他代码。。。

}

而后就是这次的重点,通过注解扫描出来的Bean,通过注解扫描出来的,自然要包含注解的信息了,所以不一样的点只有注解信息了。A君 新增ScannedGenericBeanDefinition类,代码如下:

public class ScannedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {

    /**
     * 注解信息
     */
    private final AnnotationMetadata metadata;

	//省略其他代码。。。

}

好了,就这些东西,总的来说,这部分内容并不复杂,更多的是为了补前面的坑。今天就到这里了,下班。。。

在这里插入图片描述


总结

    正所谓树欲静而风不止,欲知后事如何,请看下回分解(✪ω✪)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

穷儒公羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值