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

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君 新增SearchStrategy枚举类,代码如下:

	/**
     * 注解查找策略
     */
    enum SearchStrategy {
        /**
         * 不考虑继承关系,只获取当前类上的注解
         */
        DIRECT,
        /**
         * 继承关系只考虑@Inherited
         */
        INHERITED_ANNOTATIONS,
        /**
         * 查找直接声明的注解以及超类声明的注解。这与 INHERITED_ANNOTATIONS 类似
         * 但不依赖 @Inherited 注解
         */
        SUPERCLASS,
        /**
         * 在整个类型层次结构中进行完整搜索,包括超类和实现的接口
         */
        TYPE_HIERARCHY,
        /**
         * 在整个类型层次结构中进行搜索,包括超类、接口以及任何封闭类
         */
        TYPE_HIERARCHY_AND_ENCLOSING_CLASSES
    }

封闭类是 JDK17 的新特性,具体可以参考这篇文章,这里就不过多的解释了

重复注解容器

    普通注解直接扫描也就扫描了,但是 JDK 中,还有一类比较特别的 注解,那就是@Repeatable,意为可重复的 注解,简单理解就是一个类上可以配置多个相同的 注解。特殊人才特殊使用,注解 也是同样的道理。为此,A君 新增RepeatableContainers并给其提供几个实现。代码如下:

/**
 * 重复注解容器
 */
public abstract class RepeatableContainers {

    /**
     * 父级容器
     */
    private final RepeatableContainers parent;

    /**
     * 创建标准实现
     *
     * @return
     */
    public static RepeatableContainers standardRepeatables() {
        return StandardRepeatableContainers.INSTANCE;
    }

    /**
     * 创建显示容器
     *
     * @param repeatable
     * @param container
     * @return
     */
    public static RepeatableContainers of(
            Class<? extends Annotation> repeatable, Class<? extends Annotation> container) {

        return new ExplicitRepeatableContainer(null, repeatable, container);
    }

    /**
     * 创建空容器
     *
     * @return
     */
    public static RepeatableContainers none() {
        return NoRepeatableContainers.INSTANCE;
    }

    public RepeatableContainers and(Class<? extends Annotation> container,
                                    Class<? extends Annotation> repeatable) {
        return new ExplicitRepeatableContainer(this, repeatable, container);
    }

    Annotation[] findRepeatedAnnotations(Annotation annotation) {
        if (this.parent == null) {
            return null;
        }
        return this.parent.findRepeatedAnnotations(annotation);
    }

    /**
     * 标准实现,
     * Spring 会自动处理和管理 @Repeatable 注解及其对应的容器类。
     * 在这种情况下,Spring 会在运行时查找并解析容器注解,并将多个重复注解实例放入容器类中
     */
    private static class StandardRepeatableContainers extends RepeatableContainers {

        private static final Map<Class<? extends Annotation>, Object> cache = new ConcurrentReferenceHashMap<>();

        private static final Object NONE = new Object();

        private static StandardRepeatableContainers INSTANCE = new StandardRepeatableContainers();


        private static Method getRepeatedAnnotationsMethod(Class<? extends Annotation> annotationType) {
            Object result = cache.computeIfAbsent(annotationType,
                    StandardRepeatableContainers::computeRepeatedAnnotationsMethod);
            return (result != NONE ? (Method) result : null);
        }

        private static Object computeRepeatedAnnotationsMethod(Class<? extends Annotation> annotationType) {
            AttributeMethods methods = AttributeMethods.forAnnotationType(annotationType);
            Method method = methods.get(MergedAnnotation.VALUE);
            if (method != null) {
                Class<?> returnType = method.getReturnType();
                if (returnType.isArray()) {
                    Class<?> componentType = returnType.getComponentType();
                    if (Annotation.class.isAssignableFrom(componentType) &&
                            componentType.isAnnotationPresent(Repeatable.class)) {
                        return method;
                    }
                }
            }
            return NONE;
        }

        @Override
        Annotation[] findRepeatedAnnotations(Annotation annotation) {
            Method method = getRepeatedAnnotationsMethod(annotation.annotationType());
            if (method != null) {
                return (Annotation[]) AnnotationUtils.invokeAnnotationMethod(method, annotation);
            }
            return super.findRepeatedAnnotations(annotation);
        }
    }

    /**
     * 这个实现表示一个 显式的可重复注解容器
     * 即注解容器是明确指定的,通过显式声明容器注解(如 @Repeatable)来包含多个相同类型的注解实例
     */
    private static class ExplicitRepeatableContainer extends RepeatableContainers {

        private final Class<? extends Annotation> repeatable;

        private final Class<? extends Annotation> container;

        private final Method valueMethod;

        private Class<? extends Annotation> deduceContainer(Class<? extends Annotation> repeatable) {
            Repeatable annotation = repeatable.getAnnotation(Repeatable.class);
            return annotation.value();
        }

        @Override
        Annotation[] findRepeatedAnnotations(Annotation annotation) {
            if (this.container.isAssignableFrom(annotation.annotationType())) {
                return (Annotation[]) AnnotationUtils.invokeAnnotationMethod(this.valueMethod, annotation);
            }
            return super.findRepeatedAnnotations(annotation);
        }
    }

    /**
     * 空容器
     */
    private static class NoRepeatableContainers extends RepeatableContainers {
        
        private static NoRepeatableContainers INSTANCE = new NoRepeatableContainers();

    }

	//省略其他代码。。。
}

过滤注解

    接下来就是 注解 过滤了,过滤 注解 最简单的方式其实就是根据包名来了,当然根据类型、名称、注解什么的也可以。啥也不说了,先定义个接口再说。A君 新增AnnotationFilter接口,代码如下:

@FunctionalInterface
public interface AnnotationFilter {

    AnnotationFilter PLAIN = packages("java.lang", "com.hqd.ch03.lang");

    AnnotationFilter JAVA = packages("java", "javax");

    AnnotationFilter ALL = new AnnotationFilter() {
        @Override
        public boolean matches(Annotation annotation) {
            return true;
        }

        @Override
        public boolean matches(Class<?> type) {
            return true;
        }

        @Override
        public boolean matches(String typeName) {
            return true;
        }

    };

    static AnnotationFilter packages(String... packages) {
        return new PackagesAnnotationFilter(packages);
    }

    default boolean matches(Annotation annotation) {
        return matches(annotation.annotationType());
    }

    default boolean matches(Class<?> type) {
        return matches(type.getName());
    }

    boolean matches(String typeName);

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

A君 给他个默认实现了,就以包名进行过滤为例,整个包名过滤无非就是根据全路径进行匹配罢了。新增PackagesAnnotationFilter类,代码如下:

/**
 * 根据包名过滤注解
 */
final class PackagesAnnotationFilter implements AnnotationFilter {

    private final String[] prefixes;

    private final int hashCode;

    PackagesAnnotationFilter(String... packages) {
        this.prefixes = new String[packages.length];
        for (int i = 0; i < packages.length; i++) {
            String pkg = packages[i];
            this.prefixes[i] = pkg + ".";
        }
        Arrays.sort(this.prefixes);
        this.hashCode = Arrays.hashCode(this.prefixes);
    }

    @Override
    public boolean matches(String annotationType) {
        for (String prefix : this.prefixes) {
            if (annotationType.startsWith(prefix)) {
                return true;
            }
        }
        return false;
    }
    //省略其他方法。。。
}

注解选择器

    在 组合注解 的情况下,很可能出现多个符合条件的 注解。这时候就需要有个选择器来进行区分了。老样子,A君 新增MergedAnnotationSelector接口,代码如下:

/**
 * 注解选择策略
 *
 * @param <A>
 */
@FunctionalInterface
public interface MergedAnnotationSelector<A extends Annotation> {

    /**
     * 是否最佳匹配
     *
     * @param annotation
     * @return
     */
    default boolean isBestCandidate(MergedAnnotation<A> annotation) {
        return false;
    }

    /**
     * 选择注解
     *
     * @param existing
     * @param candidate
     * @return
     */
    MergedAnnotation<A> select(MergedAnnotation<A> existing, MergedAnnotation<A> candidate);

}

所谓选择器无非就两种形式,要么就近原则,要么第一次出现。于是,A君 新增MergedAnnotationSelectors类,将两个实现都包裹进去。代码如下:

public abstract class MergedAnnotationSelectors {

    private static final MergedAnnotationSelector<?> NEAREST = new Nearest();

    private static final MergedAnnotationSelector<?> FIRST_DIRECTLY_DECLARED = new FirstDirectlyDeclared();


    private MergedAnnotationSelectors() {
    }

    public static <A extends Annotation> MergedAnnotationSelector<A> nearest() {
        return (MergedAnnotationSelector<A>) NEAREST;
    }

    public static <A extends Annotation> MergedAnnotationSelector<A> firstDirectlyDeclared() {
        return (MergedAnnotationSelector<A>) FIRST_DIRECTLY_DECLARED;
    }

    /**
     * 就近原则
     */
    private static class Nearest implements MergedAnnotationSelector<Annotation> {
        @Override
        public boolean isBestCandidate(MergedAnnotation<Annotation> annotation) {
            return annotation.getDistance() == 0;
        }

        @Override
        public MergedAnnotation<Annotation> select(
                MergedAnnotation<Annotation> existing, MergedAnnotation<Annotation> candidate) {
            if (candidate.getDistance() < existing.getDistance()) {
                return candidate;
            }
            return existing;
        }

    }

    private static class FirstDirectlyDeclared implements MergedAnnotationSelector<Annotation> {

        @Override
        public boolean isBestCandidate(MergedAnnotation<Annotation> annotation) {
            return annotation.getDistance() == 0;
        }

        @Override
        public MergedAnnotation<Annotation> select(
                MergedAnnotation<Annotation> existing, MergedAnnotation<Annotation> candidate) {

            if (existing.getDistance() > 0 && candidate.getDistance() == 0) {
                return candidate;
            }
            return existing;
        }

    }

}

组合注解集合

    折腾了半天,总算把前提条件都准备好了,现在可以定义 组合注解集合 接口了,MergedAnnotations代码如下:

public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>> {


    /**
     * 创建组合注解集合
     *
     * @param source
     * @param annotations
     * @param repeatableContainers
     * @return
     */

    static MergedAnnotations from(Object source, Annotation[] annotations,
                                  RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) {

        return TypeMappedAnnotations.from(source, annotations, repeatableContainers, annotationFilter);
    }

    static MergedAnnotations of(Collection<MergedAnnotation<?>> annotations) {
        return MergedAnnotationsCollection.of(annotations);
    }

    <A extends Annotation> boolean isPresent(Class<A> annotationType);


    <A extends Annotation> boolean isDirectlyPresent(Class<A> annotationType);


    /**
     * 获取对应注解
     *
     * @param annotationType
     * @param <A>
     * @return
     */

    <A extends Annotation> MergedAnnotation<A> get(String annotationType,
                                                   Predicate<? super MergedAnnotation<A>> predicate,
                                                   MergedAnnotationSelector<A> selector);

    <A extends Annotation> Stream<MergedAnnotation<A>> stream(Class<A> annotationType);

    <A extends Annotation> Stream<MergedAnnotation<A>> stream(String annotationType);

    Stream<MergedAnnotation<Annotation>> stream();

	//省略其他代码。。。

}

老规矩,接下来就是具体实现类了。本以为到实现类就简单了,没想到还是头大,这破 注解 整的 A君 就没有安生过

在这里插入图片描述

想要创建出一个 组合注解集合 对象,最简单的方式就是所有 注解 由用户提供,这样子框架就什么都不用做,直接创建就行了,这种方式自然就不用细说。还有一种比较复杂,就是用户根据传过来的类、方法,由框架进行处理,这时候事情就大发了:方法还好说,只需要考虑 组合注解 的结构就行了。如果是类的话,还得考虑该类实现的接口、继承的父类,这时候就非常棘手了。A君 一阵扶额,叫苦不迭:可恶的 注解

聚合对象

    一阵吐槽过后,A君 冷静了下来。没办法,只能继续往下弄了,还是老样子,需要有个对象来描述这种情况。这个对象只需要描述类或方法、注解、注解结构三者的关系就行了。例如:

在这里插入图片描述

大致了解情况后,A君 新增Aggregate类,代码如下:

	/**
     * 类、方法上注解的结构
     */
    private static class Aggregate {
        /**
         * 所在的类索引
         */
        private final int aggregateIndex;
        /**
         * 源对象
         */
        private final Object source;
        /**
         * 拥有的注解
         */
        private final List<Annotation> annotations;
        /**
         * 注解的结构
         */
        private final AnnotationTypeMappings[] mappings;

        <A extends Annotation> MergedAnnotation<A> createMergedAnnotationIfPossible(
                int annotationIndex, int mappingIndex) {

            /**
             * 创建注解结构
             */
            return TypeMappedAnnotation.createIfPossible(
                    this.mappings[annotationIndex].get(mappingIndex), this.source,
                    this.annotations.get(annotationIndex), this.aggregateIndex);
        }
        //省略其他代码。。。
    }
注解处理器

    好了,现在进入下一个问题:用户传入某个类时,有时候需要获取到 组合注解、有时候需要判断是否存在改 注解。有多种情况,又要保持拓展。那就老样子:定义接口。A君 新增AnnotationsProcessor接口,代码如下:

/**
 * 处理注解回调
 *
 * @param <C>
 * @param <R>
 */
@FunctionalInterface
interface AnnotationsProcessor<C, R> {

    /**
     * 注解处理回调
     *
     * @param context
     * @param aggregateIndex
     * @return
     */
    default R doWithAggregate(C context, int aggregateIndex) {
        return null;
    }

    R doWithAnnotations(C context, int aggregateIndex, Object source, Annotation[] annotations);

    default R finish(R result) {
        return result;
    }
}

接下来就是具体实现了,其他基本都类似,这里就以返回 组合注解 为例。A君 新增MergedAnnotationFinder类,代码如下:

/**
     * 处理组合注解
     *
     * @param <A>
     */
    private class MergedAnnotationFinder<A extends Annotation>
            implements AnnotationsProcessor<Object, MergedAnnotation<A>> {

        private final Object requiredType;

        private final Predicate<? super MergedAnnotation<A>> predicate;

        private final MergedAnnotationSelector<A> selector;

        private MergedAnnotation<A> result;

        @Override
        public MergedAnnotation<A> doWithAnnotations(Object type, int aggregateIndex,
                                                     Object source, Annotation[] annotations) {

            for (Annotation annotation : annotations) {
                if (annotation != null && !annotationFilter.matches(annotation)) {
                    MergedAnnotation<A> result = process(type, aggregateIndex, source, annotation);
                    if (result != null) {
                        return result;
                    }
                }
            }
            return null;
        }


        private MergedAnnotation<A> process(
                Object type, int aggregateIndex, Object source, Annotation annotation) {
            /**
             * 获取可重复注解
             */
            Annotation[] repeatedAnnotations = repeatableContainers.findRepeatedAnnotations(annotation);
            if (repeatedAnnotations != null) {
                //递归处理
                return doWithAnnotations(type, aggregateIndex, source, repeatedAnnotations);
            }
            /**
             * 获取注解结构
             */
            AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(
                    annotation.annotationType(), repeatableContainers, annotationFilter);
            for (int i = 0; i < mappings.size(); i++) {
                AnnotationTypeMapping mapping = mappings.get(i);
                /**
                 * 是否匹配
                 */
                if (isMappingForType(mapping, annotationFilter, this.requiredType)) {
                    MergedAnnotation<A> candidate = TypeMappedAnnotation.createIfPossible(
                            mapping, source, annotation, aggregateIndex);
                    if (candidate != null && (this.predicate == null || this.predicate.test(candidate))) {
                        //最佳匹配
                        if (this.selector.isBestCandidate(candidate)) {
                            return candidate;
                        }
                        updateLastResult(candidate);
                    }
                }
            }
            return null;
        }

        //省略其他代码。。。
    }
注解扫描器

    注解扫描也算是一个比较公共的功能了,可以提取出一个工具类,方面大家使用,A君 新增AnnotationsScanner类。代码如下:

abstract class AnnotationsScanner {

    /**
     * 扫描对应注解的层级结构
     *
     * @param context
     * @param source
     * @param searchStrategy
     * @param processor
     * @param <C>
     * @param <R>
     * @return
     */
    static <C, R> R scan(C context, AnnotatedElement source, MergedAnnotations.SearchStrategy searchStrategy,
                         AnnotationsProcessor<C, R> processor) {

        R result = process(context, source, searchStrategy, processor);
        return processor.finish(result);
    }


    private static <C, R> R process(C context, AnnotatedElement source,
                                    MergedAnnotations.SearchStrategy searchStrategy, AnnotationsProcessor<C, R> processor) {
        /**
         *  类上注解
         */
        if (source instanceof Class) {
            return processClass(context, (Class<?>) source, searchStrategy, processor);
        }
        /**
         * 方法上注解
         */
        if (source instanceof Method) {
            return processMethod(context, (Method) source, searchStrategy, processor);
        }
        //其他情况。。
        return processElement(context, source, processor);
    }


    private static <C, R> R processClass(C context, Class<?> source,
                                         MergedAnnotations.SearchStrategy searchStrategy, AnnotationsProcessor<C, R> processor) {

        /**
         * 根据不同策略进行扫描
         */
        switch (searchStrategy) {
            case DIRECT:
                return processElement(context, source, processor);
            case INHERITED_ANNOTATIONS:
                return processClassInheritedAnnotations(context, source, searchStrategy, processor);
            case SUPERCLASS:
                return processClassHierarchy(context, source, processor, false, false);
            case TYPE_HIERARCHY:
                return processClassHierarchy(context, source, processor, true, false);
            case TYPE_HIERARCHY_AND_ENCLOSING_CLASSES:
                return processClassHierarchy(context, source, processor, true, true);
        }
        throw new IllegalStateException("Unsupported search strategy " + searchStrategy);
    }
    //省略其他代码。。。
}
基于类型的组合注解集合

    折腾了半天,总算可以定义实现类了,不过都有这么多辅助类了,实现类貌似只要躺赢就行了,不需要做其他事情了。A君 新增TypeMappedAnnotations类,代码如下:

final class TypeMappedAnnotations implements MergedAnnotations {

    static final MergedAnnotations NONE = new TypeMappedAnnotations(
            null, new Annotation[0], RepeatableContainers.none(), AnnotationFilter.ALL);


    /**
     * 源对象
     */
    private final Object source;
    /**
     * 源对象
     */
    private final AnnotatedElement element;
    /**
     * 搜索策略
     */
    private final SearchStrategy searchStrategy;

    /**
     * 包含的注解
     */
    private final Annotation[] annotations;
    /**
     * 重复注解容器
     */
    private final RepeatableContainers repeatableContainers;
    /**
     * 注解过滤器
     */
    private final AnnotationFilter annotationFilter;

    /**
     * 类型结构
     */
    private volatile List<Aggregate> aggregates;

	@Override
    public <A extends Annotation> MergedAnnotation<A> get(String annotationType,
                                                          Predicate<? super MergedAnnotation<A>> predicate,
                                                          MergedAnnotationSelector<A> selector) {

        if (this.annotationFilter.matches(annotationType)) {
            return MergedAnnotation.missing();
        }
        MergedAnnotation<A> result = scan(annotationType,
                new MergedAnnotationFinder<>(annotationType, predicate, selector));
        return (result != null ? result : MergedAnnotation.missing());
    }

	private <C, R> R scan(C criteria, AnnotationsProcessor<C, R> processor) {
        if (this.annotations != null) {
            R result = processor.doWithAnnotations(criteria, 0, this.source, this.annotations);
            return processor.finish(result);
        }
        if (this.element != null && this.searchStrategy != null) {
            return AnnotationsScanner.scan(criteria, this.element, this.searchStrategy, processor);
        }
        return null;
    }
    //省略其他代码。。。
}

测试

    折腾了这么久,命都去了半条,总算可以进入测试阶段了。A君 先随便定义个包含注解的类,HelloController代码如下:

@RequestMapping("/aa")
@Controller
public class HelloController {

    @RequestMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("message", "Form submitted successfully!");
        return "hello";
    }
}

然后就可以开始编写测试代码了,如下:

	@Test
    public void v45() throws NoSuchMethodException {
        System.out.println("############# 第四十五版: 注解篇 #############");
        // 从类注解和方法注解创建合并注解实例
        MergedAnnotation<com.hqd.ch03.v45.web.bind.annotation.RequestMapping> mergedFromClass
                = MergedAnnotations.from(com.hqd.ch03.test.web.v45.HelloController.class).get(com.hqd.ch03.v45.web.bind.annotation.RequestMapping.class);

        // 访问合并后的注解信息
        System.out.println("类注解值: " + mergedFromClass.getStringArray(MergedAnnotation.VALUE));
    }

测试结果如下:

在这里插入图片描述

没有报错就对了一半,嘿嘿。A君 总算把 注解 搞完了,后边看看 老大 还会有什么安排,今天就先到这里了,下班!

在这里插入图片描述

注:此处Spring注解扫描涉及到的内容很复杂,这篇文章这是概览,研究其设计,并没有深入。如果各位想要更细致的了解的话,可以参考下这篇博客


总结

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

穷儒公羊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值