第五十四章 Spring之假如让你来写Boot——注解篇(上)

发布于:2025-04-01 ⋅ 阅读:(22) ⋅ 点赞:(0)

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君 已经对环境相关操作进行了抽象、封装。接下来看看 A君 会有什么骚操作吧

尝试动手写IOC容器

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

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

    前情提要:A君 已经对环境相关操作进行了抽象、封装 。。。

四十五版 注解(上)

    “A君,环境部分简单吧。” 办公室内,老大 笑嘻嘻的问道

    A君 心头一凛,难道 老大 每次都是故意的,先整个简单的忽悠他。当下回答道:“还好吧。”

    “呵呵,那今天我们在前进一步,对 注解 进行支持。” 老大A君 的回答并不在意,显然,他不相信

    “注解?之前不是已经支持了吗?” A君 疑惑道

    “之前那个远远不够,既然我们准备全面拥抱 RAD,那什么xml能不要的就不要,注解 能简化的就简化!” 老大 说道

    “好的,我明白了。” A君 机械的回答道,都快成条件反射了

组合注解

    回到工位上后,来不及感叹人生之艰难,A君 就继续投入战斗中。摆在面前的第一个问题就是:如何定义 注解?如果只是简单定义个 注解,这本身本没有什么难度。如下:


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// 定义自定义注解
@Target({ElementType.METHOD, ElementType.TYPE})  // 可以用在方法或类上
@Retention(RetentionPolicy.RUNTIME)  // 在运行时保留
public @interface MyAnnotation {
    String value() default "defaultValue";  // 可以传递参数
}

这样子定义完之后,再去扫描就行了。但是现在的问题在于:如果一个类需要多个功能的 注解,那么意味着类上要申明好多个 注解,用户用着不方便,代码看着也不整洁。那咋办?A君 瞅着刚才的例子,忽然有了个大胆的想法:可以像@Target@Retention这些 元注解 一样的解决方式嘛!注解 上在套 注解,这样就可以把多个功能合成一个 注解,这样就可以大大简化了用户的配置量了。比如说可以把@Controller@ResponseBody合成一个RestController。如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {

	@AliasFor(annotation = Controller.class)
	String value() default "";
}

    既然知道了 组合注解 可以简化用户操作,那就得开始想法子处理这种需求了。其他的 A君 先不去考虑,不管这么样得先有个对象来描述它。于是,A君 先定义个接口。代码如下:


/**
 * 组合注解接口
 *
 * @param <A>
 */

public interface MergedAnnotation<A extends Annotation> {

    /**
     * 注解默认属性
     */
    String VALUE = "value";

    /**
     * 缺失注解
     */
    static <A extends Annotation> MergedAnnotation<A> missing() {
        return MissingMergedAnnotation.getInstance();
    }

    /**
     * 创建组合注解,基于已有注解
     */
    static <A extends Annotation> MergedAnnotation<A> from(A annotation) {
        return from(null, annotation);
    }

    /**
     * 创建组合注解,仅用于日志
     */
    static <A extends Annotation> MergedAnnotation<A> from(Object source, A annotation) {
        return TypeMappedAnnotation.from(source, annotation);
    }

    /**
     * 创建组合注解
     *
     * @param annotationType
     * @param <A>
     * @return
     */
    static <A extends Annotation> MergedAnnotation<A> of(Class<A> annotationType) {
        return of(null, annotationType, null);
    }

    static <A extends Annotation> MergedAnnotation<A> of(
            Class<A> annotationType, Map<String, ?> attributes) {

        return of(null, annotationType, attributes);
    }

    static <A extends Annotation> MergedAnnotation<A> of(
            AnnotatedElement source, Class<A> annotationType, Map<String, ?> attributes) {

        return of(null, source, annotationType, attributes);
    }

    static <A extends Annotation> MergedAnnotation<A> of(
            ClassLoader classLoader, Object source,
            Class<A> annotationType, Map<String, ?> attributes) {
        return TypeMappedAnnotation.of(classLoader, source, annotationType, attributes);
    }

    Class<A> getType();

    boolean isPresent();

    boolean isDirectlyPresent();

    boolean isMetaPresent();

    int getDistance();

    int getAggregateIndex();


    Object getSource();

    MergedAnnotation<?> getMetaSource();

    MergedAnnotation<?> getRoot();

    List<Class<? extends Annotation>> getMetaTypes();

    boolean hasNonDefaultValue(String attributeName);
	/**
	* 是否存在默认值
	**/
    boolean hasDefaultValue(String attributeName) throws NoSuchElementException;

    byte getByte(String attributeName) throws NoSuchElementException;
	
	//省略其他转换方法
    


    /**
     * 适配器
     */
    enum Adapt {

        /**
         * 将类或类数组属性调整为字符串。
         */
        CLASS_TO_STRING,

        /**
         * 注解转map
         */
        ANNOTATION_TO_MAP;

        public static Adapt[] values(boolean classToString, boolean annotationsToMap) {
            EnumSet<Adapt> result = EnumSet.noneOf(Adapt.class);
            addIfTrue(result, Adapt.CLASS_TO_STRING, classToString);
            addIfTrue(result, Adapt.ANNOTATION_TO_MAP, annotationsToMap);
            return result.toArray(new Adapt[0]);
        }

        private static <T> void addIfTrue(Set<T> result, T value, boolean test) {
            if (test) {
                result.add(value);
            }
        }

        protected final boolean isIn(Adapt... adaptations) {
            for (Adapt candidate : adaptations) {
                if (candidate == this) {
                    return true;
                }
            }
            return false;
        }
    }
}

接下来老规矩,提取一个抽象类。那么哪些是公共的呢?这让 A君 陷入了沉思。其实这个接口,定义了一堆方法,主要就两个的功能:一是创建注解,二是获取对应的方法返回值。那么就能从这两方面入手。A君 定义AbstractMergedAnnotation类,代码如下:

abstract class AbstractMergedAnnotation<A extends Annotation> implements MergedAnnotation<A> {

    private volatile A synthesizedAnnotation;

	/**
     * 是否生成合成注解
     *
     * @return
     */
    @Override
    public A synthesize() {
        if (!isPresent()) {
            throw new NoSuchElementException("Unable to synthesize missing annotation");
        }
        A synthesized = this.synthesizedAnnotation;
        if (synthesized == null) {
            synthesized = createSynthesizedAnnotation();
            this.synthesizedAnnotation = synthesized;
        }
        return synthesized;
    }

    @Override
    public String getString(String attributeName) {
        return getRequiredAttributeValue(attributeName, String.class);
    }

    /**
     * 根据类型获取对应注解值
     *
     * @param attributeName
     * @param type
     * @param <T>
     * @return
     */
    private <T> T getRequiredAttributeValue(String attributeName, Class<T> type) {
        T value = getAttributeValue(attributeName, type);
        if (value == null) {
            throw new NoSuchElementException("No attribute named '" + attributeName +
                    "' present in merged annotation " + getType().getName());
        }
        return value;
    }

    /**
     * 获取注解值
     *
     * @param attributeName
     * @param type
     * @param <T>
     * @return
     */
    protected abstract <T> T getAttributeValue(String attributeName, Class<T> type);

    /**
     * 创建合成注解
     *
     * @return
     */
    protected abstract A createSynthesizedAnnotation();

	//省略其他方法。。。
}

    接下来就是具体实现了,实现其实无非就是两种,一种是存在 注解,另一种就是不存在 注解。啥玩意?不存在 注解 也需要单独一个实现。这不是 A君 互吹大气,而是涉及到一种设计模式——空对象模式空对象模式 并不属于 GoF设计模式 中的任何一种,A君 也是后边才了解到的。其主要的优点是:

  1. 它可以加强系统的稳固性,能有效地减少空指针报错对整个系统的影响,使系统更加稳定
  2. 它能够实现对空对象情况的定制化的控制,掌握处理空对象的主动权
  3. 它并不依靠Client来保证整个系统的稳定运行
  4. 它通过定义isNull()对使用条件语句==null的替换,显得更加优雅,更加易懂

看的出来,前辈们也对 空指针异常 深恶痛绝,秉承着 万物皆对象 的原则,把null也封装成一个单独的对象,方便操作。既然了解到其好处,那接下来就是具体落地了。A君 新增MissingMergedAnnotation类,代码如下:

final class MissingMergedAnnotation<A extends Annotation> extends AbstractMergedAnnotation<A> {

    private static final MissingMergedAnnotation<?> INSTANCE = new MissingMergedAnnotation<>();

    private MissingMergedAnnotation() {
    }

    @Override

    public Object getSource() {
        return null;
    }

    @Override

    public MergedAnnotation<?> getMetaSource() {
        return null;
    }

    @Override
    public MergedAnnotation<?> getRoot() {
        return this;
    }

    @Override
    public List<Class<? extends Annotation>> getMetaTypes() {
        return Collections.emptyList();
    }

    @Override
    public boolean hasNonDefaultValue(String attributeName) {
        throw new NoSuchElementException(
                "Unable to check non-default value for missing annotation");
    }

    @Override
    public <T> Optional<T> getDefaultValue(String attributeName, Class<T> type) {
        return Optional.empty();
    }

    @Override
    public MergedAnnotation<A> filterAttributes(Predicate<String> predicate) {
        return this;
    }

    @Override
    public MergedAnnotation<A> withNonMergedAttributes() {
        return this;
    }

    @Override
    public AnnotationAttributes asAnnotationAttributes(Adapt... adaptations) {
        return new AnnotationAttributes();
    }

    @Override
    protected <T> T getAttributeValue(String attributeName, Class<T> type) {
        throw new NoSuchElementException(
                "Unable to get attribute value for missing annotation");
    }

    @Override
    protected A createSynthesizedAnnotation() {
        throw new NoSuchElementException("Unable to synthesize missing annotation");
    }

	//省略其他代码。。。
}
层级关系

    空对象 该返回null返回null,该抛出异常抛出异常。没有其他值得关注的地方。那接下来就可以转头实现存在 注解 的情况了。存在 注解 的情况就很麻烦了,让 A君 一阵头大:主要是因为 组合注解 存在层级结构,而且有存在别名,例如:

在这里插入图片描述

单单看类可能也没有那么直观,A君 又去简单画了个图,如下:

在这里插入图片描述

这里的ROOT节点是@SpringBootApplication,也就是 组合注解 的最后一个 注解。仔细想想其实也是,毕竟一大堆 注解 只能是积木,最终搭建出来的才是成品。这么复杂的结构必然需要一个单独的对象用以描述,不然很难进行处理了。其中主要的结构就是:元注解、父级结构、方法、别名这些东西了。A君 新增AnnotationTypeMapping类,代码如下:

final class AnnotationTypeMapping {

    private static final MirrorSets.MirrorSet[] EMPTY_MIRROR_SETS = new MirrorSets.MirrorSet[0];

    /**
     * 上级注解实例
     */
    private final AnnotationTypeMapping source;
    /**
     * 注解可以相互嵌套,这里为顶级注解
     */
    private final AnnotationTypeMapping root;
    /**
     * 注解可以相互嵌套,这里为嵌套的层级
     */
    private final int distance;

    /**
     * 注解类型
     */
    private final Class<? extends Annotation> annotationType;
    /**
     * 元注解
     */
    private final List<Class<? extends Annotation>> metaTypes;

    /**
     * 当前注解
     */
    private final Annotation annotation;
    /**
     * 注解方法
     */
    private final AttributeMethods attributes;

    private final MirrorSets mirrorSets;
    /**
     * 若该属性被 root 中的同名属性覆盖,即 aliasMappings 数组对应下标不为 -1,则记录该 root 属性下标;
     * 若该属性不被 root 中同名属性覆盖,则确定是否被子注解中的同名属性覆盖,即 conventionMappings 数组对应下标不为 -1,则记录该覆盖属性下标;
     */
    private final int[] aliasMappings;

    private final int[] conventionMappings;

    private final int[] annotationValueMappings;

    private final AnnotationTypeMapping[] annotationValueSource;

    private final Map<Method, List<Method>> aliasedBy;

    private final boolean synthesizable;

    private final Set<Method> claimedAliases = new HashSet<>();

	private void processAliases(int attributeIndex, List<Method> aliases) {
        int rootAttributeIndex = getFirstRootAttributeIndex(aliases);
        AnnotationTypeMapping mapping = this;
        while (mapping != null) {
            // 若有当前正在处理的注解中:
            // 1.有别名字段来自于root;
            // 2.别名链中有一个别名来自于该注解;
            // 则在当前处理的注解的aliasMappings上,记录这个来自于root的别名属性,表示它存在一个来自root的别名
            if (rootAttributeIndex != -1 && mapping != this.root) {
                for (int i = 0; i < mapping.attributes.size(); i++) {
                    if (aliases.contains(mapping.attributes.get(i))) {
                        mapping.aliasMappings[i] = rootAttributeIndex;
                    }
                }
            }
            mapping.mirrorSets.updateFrom(aliases);
            mapping.claimedAliases.addAll(aliases);
            if (mapping.annotation != null) {
                int[] resolvedMirrors = mapping.mirrorSets.resolve(null,
                        mapping.annotation, AnnotationUtils::invokeAnnotationMethod);
                for (int i = 0; i < mapping.attributes.size(); i++) {
                    if (aliases.contains(mapping.attributes.get(i))) {
                        this.annotationValueMappings[attributeIndex] = resolvedMirrors[i];
                        this.annotationValueSource[attributeIndex] = mapping;
                    }
                }
            }
            mapping = mapping.source;
        }
    }

	private void addConventionMappings() {
        if (this.distance == 0) {
            return;
        }
        AttributeMethods rootAttributes = this.root.getAttributes();
        int[] mappings = this.conventionMappings;
        for (int i = 0; i < mappings.length; i++) {
            /**
             * 获取方法名
             * 如果root节点存在对应的方法名则记录该下标
             */
            String name = this.attributes.get(i).getName();
            int mapped = rootAttributes.indexOf(name);
            if (!MergedAnnotation.VALUE.equals(name) && mapped != -1) {
                mappings[i] = mapped;
                MirrorSets.MirrorSet mirrors = getMirrorSets().getAssigned(i);
                if (mirrors != null) {
                    for (int j = 0; j < mirrors.size(); j++) {
                        mappings[mirrors.getAttributeIndex(j)] = mapped;
                    }
                }
            }
        }
    }

	//省略其他方法。。。
}

获取源对象

    除却 注解 的层级关系,有些 注解 可能在执行的过程中被封装成Map,也有可能是其他对象,故此 A君 在定义ValueExtractor接口,用以获取真正的 注解。代码如下:

@FunctionalInterface
interface ValueExtractor {
    Object extract(Method attribute, Object object);
}

该准备的都准备好了,接下来就可以提供真正的实现类了,那就是TypeMappedAnnotation。代码如下:

final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnnotation<A> {

    private static final Map<Class<?>, Object> EMPTY_ARRAYS;

    static {
        Map<Class<?>, Object> emptyArrays = new HashMap<>();
        emptyArrays.put(boolean.class, new boolean[0]);
        emptyArrays.put(byte.class, new byte[0]);
        emptyArrays.put(char.class, new char[0]);
        emptyArrays.put(double.class, new double[0]);
        emptyArrays.put(float.class, new float[0]);
        emptyArrays.put(int.class, new int[0]);
        emptyArrays.put(long.class, new long[0]);
        emptyArrays.put(short.class, new short[0]);
        emptyArrays.put(String.class, new String[0]);
        EMPTY_ARRAYS = Collections.unmodifiableMap(emptyArrays);
    }

    /**
     * 组合注解的层级关系
     */
    private final AnnotationTypeMapping mapping;
    /**
     * 类加载器
     */
    private final ClassLoader classLoader;
    /**
     * 上级节点
     */
    private final Object source;
    /**
     * root节点
     */
    private final Object rootAttributes;

    /**
     * 获取注解
     */
    private final ValueExtractor valueExtractor;
    /**
     * 注解总数
     */
    private final int aggregateIndex;

    private final boolean useMergedValues;

    private final Predicate<String> attributeFilter;

    private final int[] resolvedRootMirrors;

    private final int[] resolvedMirrors;

 	@Override
    protected A createSynthesizedAnnotation() {
        /**
         * 目标注解是root且root节点非合成注解
         */
        if (isTargetAnnotation(this.rootAttributes) && !isSynthesizable((Annotation) this.rootAttributes)) {
            return (A) this.rootAttributes;
        } else if (isTargetAnnotation(this.mapping.getAnnotation()) && !isSynthesizable(this.mapping.getAnnotation())) {
            return (A) this.mapping.getAnnotation();
        }
        return SynthesizedMergedAnnotationInvocationHandler.createProxy(this, getType());
    }

    private boolean isTargetAnnotation(Object obj) {
        return getType().isInstance(obj);
    }


    @Override
    protected <T> T getAttributeValue(String attributeName, Class<T> type) {
        int attributeIndex = getAttributeIndex(attributeName, false);
        return (attributeIndex != -1 ? getValue(attributeIndex, type) : null);
    }

    private int getAttributeIndex(String attributeName, boolean required) {
        int attributeIndex = (isFiltered(attributeName) ? -1 : this.mapping.getAttributes().indexOf(attributeName));
        if (attributeIndex == -1 && required) {
            throw new NoSuchElementException("No attribute named '" + attributeName +
                    "' present in merged annotation " + getType().getName());
        }
        return attributeIndex;
    }
	//省略其他代码。。。
}
	

    没想到一个小小的 注解 这么麻烦,A君 一阵无言,看样子今天是搞不完了,天色也不早了,只能明天继续了。。。

在这里插入图片描述


总结

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


网站公告

今日签到

点亮在社区的每一天
去签到