SpringBoot自动配置原理解析 | 京东物流技术团队

news2024/9/24 17:20:29

1: 什么是SpringBoot自动配置

首先介绍一下什么是SpringBoot,SpringBoost是基于Spring框架开发出来的功能更强大的Java程序开发框架,其最主要的特点是:能使程序开发者快速搭建一套开发环境。SpringBoot能将主流的开发框架(例如SpringMVC,Dubbo,Mybatis,Redis等),做到像Maven导入Jar包一样的简洁快速,做到开箱即用。其中最关键的技术就是SpringBoot定制的各种Starter,通Maven引入Starter就能快速搭建开发环境。

2: SpringBoot Starter自动装配案例

在以前单独使用SpringMVC Web编程框架时,我们需要单独配置_DispatcherServletTomcat,使用SpringBoot之后,我们只需要引入SpringBoot-Starter-Web就能直接开始编写Controller等Web相关的代码,这就是SpringBoot为们提供的开箱即用的便捷能力,下面就以SpringBoot-Starter-Web_来说明SpringBoot自动配置的关键原理

3: SpringBoot自动装配案例源码解析

3.1 DispatcherServlet的自动配置原理

首先我们定位到SpringBoot自动配置的Maven依赖

     <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
        <version>${spring-boot.version}</version>
      </dependency>

在依赖的Jar包中我们可以在_META-INF/spring.factories_中找到自动配置类:

org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration

在这个类中存在有一个静态内部类:

org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration.DispatcherServletConfiguration

下图是这个配置类的主要源码和解析:

下面将上图中关键的注解功能,分别进行功能说明

3.1.1:@EnableConfigurationProperties({WebMvcProperties.class})注解解析

这个注解表示使_WebMvcProperties.class类上的@ConfigurationProperties这个注解生效,同时@ConfigurationProperties这个注解是将application.xml中以spring.mvc开头的配置参数自动注入到WebMvcProperties.class_类的字段中

3.1.2:@Conditional({DefaultDispatcherServletCondition.class}注解解析

该注解的原理就是将满足特定条件情况下的Bean自动加载到Spring容器中,该注解对应的Spring接口就是_org.springframework.context.annotation.Condition_这个接口

public interface Condition {
    boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}

3.1.3:@ConditionOnClass注解解析

_@ConditionOnClass这个注解是在当程序代码环境classpath下存在xxx.class的情况下条件成立,同时最终也会调用到matches_方法中,其中关键的源码如下:

protected static Class<?> resolve(String className, ClassLoader classLoader) throws ClassNotFoundException {
    return classLoader != null ? Class.forName(className, false, classLoader) : Class.forName(className);
}

从上面可以看到,代码利用_Class.forName方法加载classpath下的xxx.class类,如果加载成功条件就会成立。最后,在满足了所有**@ConditionOnal**注解条件后,SpringBoot就会自动为我们在Spring容器中注入DispatcherServlet了,无需单独配置了,直接引入spring-boot-starter-web_r即可开始使用web相关功能。

3.1.4:总结

我们以DispatcherServlet是如何自动配置到容器中为例,探究了SpringBoot Starter的自动配置原理,其中涉及了几个关键的注解和步骤:

第一步:涉及到了配置文件的读取和个性化配置,这里就涉及到了下面这两个注解

@ConfigurationProperties
@EnableConfigurationProperties

第二步:设计到了在什么条件下才自动配置的注解

@Conditional
@ConditionalOnClass

第三步:约定了自动配置类的加载路径

/META-INF/spring-factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=自动配置类全路径名称

在我们了解到了SpringBoot自动配置的原理之后,我们就可以自定义一个SpringBoot Starter来快速搭建我们的开发环境了

4:自定义一个打印输入输出日志的Starter

4.1 首先定义一个标记需要打印出入参日志的注解@PrintLog

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PrintLog {
}

4.2 定义一个存放打印日志配置的实体类

//自动注入application配置文件中已log.switch开头的配置参数
@ConfigurationProperties("log.switch")
public class LogProperties {
    //是否启用打印日志功能
    private Boolean enabled = false;
    //是否打印调用者ip
    private Boolean printIp = false;
    //是否打印调用者url
    private Boolean printUrl = false
}

4.3 定义一个@PrintLog注解的切面类

@Aspect
public class LogAspect {
    private static final Log LOGGER = LogFactory.getLog(LogAspect.class);
    private LogProperties logProperties;
    
    @Pointcut("@annotation(com.zl.annotation.PrintLog)")
    public void Log(){}

    @Around("Log()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String methodName = method.getName();
        //打印调用url
        if (Boolean.TRUE.equals(logProperties.getPrintUrl())){
            LOGGER.info("URL:" + request.getRequestURL().toString());
        }
        //打印ip
        if (Boolean.TRUE.equals(logProperties.getPrintIp())) {
            LOGGER.info("IP :" + request.getRemoteAddr());
        }
        //打印方法
        LOGGER.info("method :" + methodName);
        //打印参数
        LOGGER.info("parameter :" + Arrays.toString(joinPoint.getArgs()));
        Object result = joinPoint.proceed();
        //打印返回结果
        LOGGER.info("return :" + JSON.toJSONString(result));
        return result;
    }
}

4.4 定义一个打印日志的自动配置类

@Configuration
@EnableConfigurationProperties({LogProperties.class})
//表示在application配置文件中必须配置log.switch.enabled = true才启动自动配置
@ConditionalOnProperty(prefix = "log.switch", value = "enabled", havingValue = "true")
public class LogAutoConfigure {
    @Bean
    //Advice.class是aop切面中关键的切面方法类(@Before,@After等)
    //程序中有Advice.class类说明需要使用切面功能,这时才加载自定义的切面类
    @ConditionalOnClass(Advice.class)
    public LogAspect webLogAspect(LogProperties logProperties){
        return new LogAspect(logProperties);
    }
}

@ConditionalOnProperty表示在application配置文件中必须存在相应的配置才能使条件成立

4.5 配置自定义配置类的加载路径

META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.zl.autoConfigure.LogAutoConfigure

4.6 Maven打包部署

maven install

5:开始使用自定义的Starter

5.1 在项目中引入Starter

<dependency>
   <groupId>com.zl.demo</groupId>
   <artifactId>LogStarter</artifactId>
   <version>1.0-SNAPSHOT</version>
</dependency>

5.2 在application.yml中配置参数

log:
  switch:
    enabled: true //启用打印日志功能
    printIp: true //打印请求ip
    printUrl: true //打印请求url

经过上面两个步骤就,打印日志的功能就已经开启了,接下来就可以进行编码测试了

5.3 定义一个Controller并标上打印日志的注解

@RestController
@RequestMapping("/test")
public class HelloWorldController {
    @PrintLog
    @RequestMapping("/hello")
    public String helleWorld(String test){
        return "hello world!";
    }
}

5.4 启动项目开始测试

com.zl.aspect.LogAspect   : URL:http://localhost:8080/test/hello
com.zl.aspect.LogAspect   : IP :0:0:0:0:0:0:0:1
com.zl.aspect.LogAspect   : method :helleWorld
com.zl.aspect.LogAspect   : parameter :[test]
com.zl.aspect.LogAspect   : return :"hello world!"

可以看到上面的入参和返回值都已经打印出来了,说明了自定义的starter已经生效了。

6:总结

SpringBoot自动配置功能带给我们的是开箱即用,快速便捷的功能,自动配置为我们研发人员带来的优点,我主要总结为以下两点:

1:提高研发效率。我们可以快速构建开发环境,对于开发中使用到的开源组件和中间件,我们直接引入对应的Starter就可以直接开发了,例如Redis和Mybatis等,可以直接引入对应的_spring-boot-starter-data-redis就可以直接使用RedisTemplate来操作Redis了,这样可以极大的提高研发的效率,无需再进行复杂的起步配置了和各种版本依赖管理了。

2:标准模块复用。对于业务开发中的一些_标准模块,例如常用的一些三方服务,我们可以利用Starter直接配置好,在需要使用的项目中直接引入这个starter就可以立即使用了,无需再去引入Jar包和编写配置文件等,同样的,对于一些标准非业务强耦合的功能_,例如监控,鉴权等,也可以定义一个Starter,需要使用鉴权和监控功能的项目就可以直接复用了,无需再次开发。

作者:京东零售 钟磊

来源:京东云开发者社区 自猿其说Tech 转载请注明来源

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1131340.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二甲医院his系统源码,医院信息管理系统全套源码 电子病历评级4级

医院his系统源码&#xff0c;医院信息管理系统全套源码 电子病历评级4级 HIS系统完全基于云端部署&#xff0c;采用B/S架构&#xff0c;并通过软件即服务&#xff08;SaaS&#xff09;的形式面向二级医院的可快速交付、便捷运维、云化的医院核心业务平台产品。融合医院HIS和EMR…

CTF取证技术实战,图片、文件、流等相关内容的取证技术

I、背景 取证技术&#xff0c;尤其是计算机数据取证技术&#xff0c;是一种针对信息犯罪和计算机数据的专业取证技术。它旨在帮助学习者理解电子证据及其形成过程&#xff0c;并掌握计算机数据相关的取证技术。 具体来说&#xff0c;计算机取证是对计算机犯罪证据的识别获取、…

RetentionPolicy枚举类

包名package java.lang.annotation 作用 注释保留策略。此枚举类型的常量描述用于保留注释的各种策略。它们被使用与&#xff5b; Retention&#xff5d;元注释类型一起指定注释要保留多长时间。 属性 SOURCE编译器将丢弃注释。CLASS注释将由编译器记录在类文件…

组件通信-跨级通信Provide | Inject

使用 provide/inject &#xff0c;只需要向后代注入组件本身&#xff08;this&#xff09;&#xff0c;后代组件中可以无视层级任意访问祖先组件中的状态。 当然它也有缺点&#xff1a;因为 provide/inject 中变量的修改是无法控制的。换句话说&#xff0c;不知道是哪个组件修…

Python网络编程之数据的主机字节序与网络字节序

在Python网络编程中&#xff0c;需要将数据通过网络在服务端与客户端中传递。而数据在主机中和在网络中保存的方式是不同的&#xff0c;即主机字节序和网络字节序。 1 介绍 1.1 主机字节序 数据的主机字节序指的是在高位内存保存数据的高位&#xff0c;在低位内存保存数据的…

霸王条款惹品牌争议,京东双11站在商家对立面?

作者 | 江北 来源 | 洞见新研社 双11活动第一天&#xff0c;京东就站上了风口浪尖。 与烘焙烤箱品牌海氏的话题接连登上微博热搜&#xff0c;海氏控诉京东滥用市场竞争地位&#xff0c;破坏市场竞争秩序。在海氏的声明中&#xff0c;京东的行为让吃瓜群众大开眼界&#xff1a…

HackTheBox---Starting Point-- Tier 0---Meow

文章目录 一 题目二 实验过程 一 题目 Tags Telnet、Network、Protocols、Reconnaissance、Weak Credentials、Misconfiguration译文&#xff1a;标签、远程登录、网络、协议、侦察、弱凭证、配置错误Connect To attack the target machine, you must be on the same networ…

深度学习--通过对Keras进行微调提升性能

本文使用微调(Fine-tune)技术来提升模型的性能。前面我们通过迁移学习将这个猫狗大战二分类问题的预测准确率提升到了90%左右,看上去效果已经很不错了,但是还能不能进一步提升了呢? 前面我们没有对VGG16的卷积层进行参数的优化,那么我们这里就可以来优化这部分的参数。由…

67 跳跃游戏 II

跳跃游戏 II 题解1 贪心1 正向题解2 贪心2 反向题解3 DP 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处: 0 &…

前端实现菜单按钮级权限

核心思想就是通过登录请求此用户对应的权限菜单&#xff0c;然后跳转首页&#xff0c;触发全局前置导航守卫&#xff0c;在全局导航守卫中通过 addRoute 添加动态路由进去。addRoute有一个需要注意的地方&#xff0c;就是我们添加完动态路由后&#xff0c;地址栏上立即访问添加…

Linux PAGE_ALIGN 宏定义的理解

前言 最近再阅读 Linux ion&#xff08;一种内存分配管理&#xff09;时&#xff0c;遇到了 PAGE_ALIGN 宏&#xff0c;这个宏到底是怎么工作的&#xff1f; 【页对齐】时什么意思&#xff1f; 页大小就是 4096 吗&#xff1f; 追踪 PAGE_ALIGN 通过一步一步的追踪&#xff0…

基于自动化工具autox.js的抢票(猫眼)

1.看到朋友圈抢周杰伦、林俊杰演唱会票贼难信息,特研究了一段时间,用autox.js写了自动化抢票脚本,购票页面自动点击下单(仅限安卓手机)。 2.脚本运行图 3.前期准备工作 (1)autox.js社区官网:AutoX.js (2)b站上学习资料:10分钟学会AutoX.js hello world_哔哩哔哩_bi…

下一个风口在哪里?云计算:未来十年最有潜力行业!

近年来&#xff0c;中国云计算产业发展迅猛&#xff0c;保持30%以上的年均增长率&#xff0c;成为全球增速最快的市场之一&#xff0c;云计算应用领域正向制造、政务、金融、医疗、教育等企业级市场延伸拓展。 目前&#xff0c;云计算应用的普及促使开源技术广受关注&#xff…

工控安全与网络安全有什么不同?

在当代&#xff0c;全球制造业正在经历一场前所未有的技术变革。工业4.0不仅代表着自动化和数据交换的进步&#xff0c;它还揭示了工业自动化、智能制造与系统集成的融合。这种集成为企业带来了效率和质量的双重提升&#xff0c;但同时也暴露出新的安全隐患。工控系统成为了这一…

守护线程:当一个线程使用setDaemon后,便成了守护线程,当守护线程结束,其相关线程也相应结束

public static void main(String[] args) throws InterruptedException {MyDaemonThread myDaemonThread new MyDaemonThread();//如果我们希望当main线程结束后&#xff0c;子线程自动结束//我们只需要将子线程设置为守护线程即可myDaemonThread.setDaemon(true);myDaemonThr…

机械设计制造,设计行业图纸透明加密保护。防止内部终端核心文件数据、资料外泄

当下互联网时代&#xff0c;许多设计单位的设计图纸都是以电子文件的形式存在于终端电脑和服务器上。在图纸的设计生产过程中&#xff0c;必定会经过多个部门人员之手&#xff0c;此过程中就隐藏着巨大的风险。所以&#xff0c;设计单位需要使用专业的图纸加密软件来保护内部图…

设计模式(14)备忘录模式

一、介绍&#xff1a; 1、定义&#xff1a;是一种行为设计模式&#xff0c;它允许将对象的内部状态保存在一个备忘录对象中&#xff0c;并在需要时恢复对象的状态&#xff0c;而不破坏对象的封装性。 2、使用场景&#xff1a; &#xff08;1&#xff09;当需要保存和恢复对象…

xcheck插件安装到idea中

一、安装xcheck-cli 1.部署好xbox环境之后&#xff0c;在 xcheck 页面右上角&#xff0c;点击帮助进入帮助中心&#xff0c;切换至资源下载tab&#xff0c;进入资源下载页面&#xff0c;下载好所需要的版本&#xff0c;我需要的是windows版本的xcheck-cli和xcheck-idea插件 2.添…

基于ssm卤菜销售系统

基于ssm卤菜销售系统 摘要 基于SSM&#xff08;Spring、SpringMVC、MyBatis&#xff09;框架的卤菜销售系统是一种现代化的食品销售管理系统&#xff0c;旨在提高卤菜店铺的效率、准确性和客户满意度。该系统通过整合多个关键组件&#xff0c;实现了卤菜销售业务的自动化管理&a…