Spring5 新特性 - spring.components

简介: 《基础系列》

解析

  • 相关类: org.springframework.context.index.CandidateComponentsIndexLoader
  • 测试用例: org.springframework.context.annotation.ClassPathScanningCandidateComponentProviderTests.defaultsWithIndex,org.springframework.context.index.CandidateComponentsIndexLoaderTests
  • CandidateComponentsIndexLoader是怎么找出来的,全文搜索spring.components

使用介绍

  • 下面是从resources/example/scannable/spring.components测试用例中复制过来的,从中可以发现等号左侧放的是我们写的组件,等号右边是属于什么组件
example.scannable.AutowiredQualifierFooService=example.scannable.FooService
example.scannable.DefaultNamedComponent=org.springframework.stereotype.Component
example.scannable.NamedComponent=org.springframework.stereotype.Component
example.scannable.FooService=example.scannable.FooService
example.scannable.FooServiceImpl=org.springframework.stereotype.Component,example.scannable.FooService
example.scannable.ScopedProxyTestBean=example.scannable.FooService
example.scannable.StubFooDao=org.springframework.stereotype.Component
example.scannable.NamedStubDao=org.springframework.stereotype.Component
example.scannable.ServiceInvocationCounter=org.springframework.stereotype.Component
example.scannable.sub.BarComponent=org.springframework.stereotype.ComponentCopy to clipboardErrorCopied

debug

  • 入口 org.springframework.context.index.CandidateComponentsIndexLoader.loadIndex
@Nullable
    public static CandidateComponentsIndex loadIndex(@Nullable ClassLoader classLoader) {
        ClassLoader classLoaderToUse = classLoader;
        if (classLoaderToUse == null) {
            classLoaderToUse = CandidateComponentsIndexLoader.class.getClassLoader();
        }
        return cache.computeIfAbsent(classLoaderToUse, CandidateComponentsIndexLoader::doLoadIndex);
    }
Copy to clipboardErrorCopied
/**
     * 解析  META-INF/spring.components 文件
     * @param classLoader
     * @return
     */
    @Nullable
    private static CandidateComponentsIndex doLoadIndex(ClassLoader classLoader) {
        if (shouldIgnoreIndex) {
            return null;
        }
        try {
            Enumeration<URL> urls = classLoader.getResources(COMPONENTS_RESOURCE_LOCATION);
            if (!urls.hasMoreElements()) {
                return null;
            }
            List<Properties> result = new ArrayList<>();
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                // 读取META-INF/spring.components文件转换成map对象
                Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
                result.add(properties);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Loaded " + result.size() + "] index(es)");
            }
            int totalCount = result.stream().mapToInt(Properties::size).sum();
            // 查看CandidateComponentsIndex方法
            return (totalCount > 0 ? new CandidateComponentsIndex(result) : null);
        }
        catch (IOException ex) {
            throw new IllegalStateException("Unable to load indexes from location [" +
                    COMPONENTS_RESOURCE_LOCATION + "]", ex);
        }
    }
Copy to clipboardErrorCopied
CandidateComponentsIndex(List<Properties> content) {
        this.index = parseIndex(content);
    }
    /**
     * 解析  MATE-INF\spring.components 转换成 map
     *
     * @param content
     * @return
     */
    private static MultiValueMap<String, Entry> parseIndex(List<Properties> content) {
        MultiValueMap<String, Entry> index = new LinkedMultiValueMap<>();
        for (Properties entry : content) {
            entry.forEach((type, values) -> {
                String[] stereotypes = ((String) values).split(",");
                for (String stereotype : stereotypes) {
                    index.add(stereotype, new Entry((String) type));
                }
            });
        }
        return index;
    }Copy to clipboardErrorCopied

  • 该类给org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents提供了帮助
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
        // 扫描
        /**
         * if 测试用例: {@link org.springframework.context.annotation.ClassPathScanningCandidateComponentProviderTests#defaultsWithIndex()}
         * 解析 spring.components文件
         */
        if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
            return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
        }
        else {
            return scanCandidateComponents(basePackage);
        }
    }
相关文章
|
负载均衡 Java API
Spring Cloud是什么及基本特性都有哪些?
Spring Cloud 是用于构建健壮云应用的框架,包含多个子项目。其核心组件如Eureka(服务注册与发现)、Hystrix(熔断器)、Ribbon(负载均衡)等,帮助开发者快速实现微服务架构。Spring Cloud 提供了服务注册与发现、分布式配置、路由、断路器等功能,简化了微服务开发与管理。本文将重点介绍服务注册与发现及分布式配置两大特性。
833 5
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
570 4
|
10月前
|
Java 数据库连接 API
Java 8 + 特性及 Spring Boot 与 Hibernate 等最新技术的实操内容详解
本内容涵盖Java 8+核心语法、Spring Boot与Hibernate实操,按考试考点分类整理,含技术详解与代码示例,助力掌握最新Java技术与应用。
311 2
|
安全 前端开发 Java
随着企业应用复杂度提升,Java Spring框架以其强大与灵活特性简化开发流程,成为构建高效、可维护应用的理想选择
随着企业应用复杂度提升,Java Spring框架以其强大与灵活特性简化开发流程,成为构建高效、可维护应用的理想选择。依赖注入使对象管理交由Spring容器处理,实现低耦合高内聚;AOP则分离横切关注点如事务管理,增强代码模块化。Spring还提供MVC、Data、Security等模块满足多样需求,并通过Spring Boot简化配置与部署,加速微服务架构构建。掌握这些核心概念与工具,开发者能更从容应对挑战,打造卓越应用。
262 1
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
285 0
|
XML Java 测试技术
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
这篇文章介绍了Spring5框架的三个新特性:支持@Nullable注解以明确方法返回、参数和属性值可以为空;引入函数式风格的GenericApplicationContext进行对象注册和管理;以及如何整合JUnit5进行单元测试,同时讨论了JUnit4与JUnit5的整合方法,并提出了关于配置文件加载的疑问。
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
|
监控 Java 应用服务中间件
SpringBoot是如何简化Spring开发的,以及SpringBoot的特性以及源码分析
Spring Boot 通过简化配置、自动配置和嵌入式服务器等特性,大大简化了 Spring 应用的开发过程。它通过提供一系列 `starter` 依赖和开箱即用的默认配置,使开发者能够更专注于业务逻辑而非繁琐的配置。Spring Boot 的自动配置机制和强大的 Actuator 功能进一步提升了开发效率和应用的可维护性。通过对其源码的分析,可以更深入地理解其内部工作机制,从而更好地利用其特性进行开发。
590 6
|
安全 Java 开发者
强大!Spring Cloud Gateway新特性及高级开发技巧
在微服务架构日益盛行的今天,网关作为微服务架构中的关键组件,承担着路由、安全、监控、限流等多重职责。Spring Cloud Gateway作为新一代的微服务网关,凭借其基于Spring Framework 5、Project Reactor和Spring Boot 2.0的强大技术栈,正逐步成为业界的主流选择。本文将深入探讨Spring Cloud Gateway的新特性及高级开发技巧,助力开发者更好地掌握这一强大的网关工具。
903 6
|
Java Kotlin 索引
学习Spring框架特性及jiar包下载
Spring 5作为最新版本,更新了JDK基线至8,修订了核心框架,增强了反射和接口功能,支持响应式编程及Kotlin语言,引入了函数式Web框架,并提升了测试功能。Spring框架可在其官网下载,包括文档、jar包和XML Schema文档,适用于Java SE和Java EE项目。
|
存储 Java 开发者
使用Spring Boot 3.3全新特性CDS,启动速度狂飙100%!
【8月更文挑战第30天】在快速迭代的软件开发周期中,应用的启动速度是开发者不可忽视的一个重要指标。它不仅影响着开发效率,还直接关系到用户体验。随着Spring Boot 3.3的发布,其中引入的Class Data Sharing(CDS)技术为应用的启动速度带来了革命性的提升。本文将围绕这一全新特性,深入探讨其原理、使用方法以及带来的实际效益,为开发者们带来一场技术盛宴。
1167 2