Spring Boot源码分析(设置字符编码实现原理)

配置类(一般都是只读文件)的好处:众所周知,SSM框架中各种复杂的配置让其得到配置地狱这一称号,而sprint boot框架避免了手写繁琐的XML文件,不用自己配置,一切springboot都帮我们配置好了。

IDEA中为何在application.properties中写上

spring.http.encoding.charset= us-ascii

时可以自动将默认的UTF-8编码改成us-ascii编码呢?本文源码分析这个自动装配功能是怎么实现的。

首先我们在IDEA中找到实现该功能的配置类

步骤如下:

1、

在IDEA中用Maven创立一个springboot项目后点击External Libraries

 

2,在META-INF下找到spring.factories文件

 

 3,打开spring.factories并找到Auto Configure注释,其后声明了所有第三方依赖

功能解释:spring boot在启动时会根据META-INF/spring factories找到文件中的第三方依赖并自动配置,所以这是不用自己手写第三方依赖XML文件从而避免繁琐的原因

4,那么spring.factories中声明的第三方依赖在哪里呢?如图箭头所示,第三方依赖放在和META-INF同级的一个包中,这是整个J2EE整合体系所需的依赖

 

5,点击org.springframework.boot.autoconfugue,可以看到很多不同种类的依赖包

6,本文是解释字符编码自动配置原理,字符编码是属于web功能的,所以我们要找到web依赖包,并找到配置类HttpEncodeingAutoConfiguration.class并打开

7, 找到@EnableConfigurationProperties的注解

 

下面是 HttpProperties.class源码:


// Source code recreated from a .class file by IntelliJ IDEA    (翻译:由IntelliJ IDEA从.class文件重新创建的源代码,说明这个不是spring boot官方源代码)
// (powered by Fernflower decompiler) (翻译:Fernflower反编译器提供动力,人间迷惑行为有木有?)


//

package org.springframework.boot.autoconfigure.http;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(      
    prefix = "spring.http"     //prefix前缀,在application.properties中可通过前缀调用
)
public class HttpProperties {
    private boolean logRequestDetails;
    private final HttpProperties.Encoding encoding = new HttpProperties.Encoding();
//HttpProperties.Encoding表示调用静态内部类Encoding生成一个静态内部类对象encoding

    public HttpProperties() {   //HttpProperties类的无参构造方法
    }

    public boolean isLogRequestDetails() {
        return this.logRequestDetails;
    }

    public void setLogRequestDetails(boolean logRequestDetails) {
        this.logRequestDetails = logRequestDetails;
    }

    public HttpProperties.Encoding getEncoding() {
        return this.encoding;
    }

    public static class Encoding {    //HttpProperties的静态内部类Encoding
        public static final Charset DEFAULT_CHARSET;//PS:JAVA中所有被 final 修饰的量都是常量 也就是该量的值是不变的,用static主要作用是在类刚加载时就初始化该量的值并给他分配一块共用的内存块存储他的值。
        private Charset charset;//声明一个private可见的Charset类型的变量,变量名为charset;
        private Boolean force;
        private Boolean forceRequest;
        private Boolean forceResponse;
        private Map<Locale, Charset> mapping;

        public Encoding() {//静态内部类Encoding的无参构造方法将本类的charset变量赋值为DEFAULT_CHARSET
            this.charset = DEFAULT_CHARSET;
        }

        public Charset getCharset() {
            return this.charset;
        }

        public void setCharset(Charset charset) {
            this.charset = charset;
        }

        public boolean isForce() {
            return Boolean.TRUE.equals(this.force);
        }

        public void setForce(boolean force) {
            this.force = force;
        }

        public boolean isForceRequest() {
            return Boolean.TRUE.equals(this.forceRequest);
        }

        public void setForceRequest(boolean forceRequest) {
            this.forceRequest = forceRequest;
        }

        public boolean isForceResponse() {
            return Boolean.TRUE.equals(this.forceResponse);
        }

        public void setForceResponse(boolean forceResponse) {
            this.forceResponse = forceResponse;
        }

        public Map<Locale, Charset> getMapping() {
            return this.mapping;
        }

        public void setMapping(Map<Locale, Charset> mapping) {
            this.mapping = mapping;
        }

        public boolean shouldForce(HttpProperties.Encoding.Type type) {
            Boolean force = type != HttpProperties.Encoding.Type.REQUEST ? this.forceResponse : this.forceRequest;
            if (force == null) {
                force = this.force;
            }

            if (force == null) {
                force = type == HttpProperties.Encoding.Type.REQUEST;
            }

            return force;
        }

        static {           
            DEFAULT_CHARSET = StandardCharsets.UTF_8;//(后面StandardCharsets类的源码,此处使用了 StandardCharsets类的静态常量UTF_8)
        }

//PS:静态语句块:static{}(即static块),会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法                                                                                                                                 

      public static enum Type {
            REQUEST,
            RESPONSE;

            private Type() {
            }
        }
    }
}

 

 StandardCharsets.class源码(非IDEA重写的官方源码):

此类含有各种字符集静态常量

第一段注释翻译:

标准{@link Charset字符集}的常量定义。这些字符集保证在Java平台的每个实现上都可用。

/**
 * Constant definitions for the standard {@link Charset Charsets}. These
 * charsets are guaranteed to be available on every implementation of the Java
 * platform.
 *
 * @see <a href="Charset#standard">Standard Charsets</a>
 * @since 1.7
 */
public final class StandardCharsets {          //当用final修饰一个类时,表明这个类不能被继承

    private StandardCharsets() {      
        throw new AssertionError("No java.nio.charset.StandardCharsets instances for you!");
    }
//private修饰构造方法表明当外部new一个StandardCharsets对象时会抛出AssertionError异常
   
 /**
     * Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the
     * Unicode character set
     */
    public static final Charset US_ASCII = Charset.forName("US-ASCII");
    /**
     * ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1
     */
    public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
    /**
     * Eight-bit UCS Transformation Format
     */
    public static final Charset UTF_8 = Charset.forName("UTF-8");
    /**
     * Sixteen-bit UCS Transformation Format, big-endian byte order
     */
    public static final Charset UTF_16BE = Charset.forName("UTF-16BE");
    /**
     * Sixteen-bit UCS Transformation Format, little-endian byte order
     */
    public static final Charset UTF_16LE = Charset.forName("UTF-16LE");
    /**
     * Sixteen-bit UCS Transformation Format, byte order identified by an
     * optional byte-order mark
     */
    public static final Charset UTF_16 = Charset.forName("UTF-16");
}

最后总结一下

的完整内部调用过程:

1,spring.http为前缀,使用它相当于调用HttpProperties类

2,spring.http.encoding相当于调用HttpProperties类的静态encoding方法

3,spring.http.encoding.charset相当于调用HttpProperties类的静态encoding方法的charset变量

 4,最后一步给charset变量赋字符集

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot源码分析涉及到多个类和方法。其,方法org.springframework.boot.SpringApplication#prepareContext用于准备应用程序的上下文,并返回一个配置好的Spring应用程序上下文。 Spring Boot的主要目的是简化Spring框架繁复的配置问题。它通过提供自动配置、约定优于配置和快速开发的原则来实现这一目标。具体来说,它使用了一系列机制来简化开发者的工作,包括自动配置、自动扫描、自动装配等。 在Spring Boot应用程序,这些机制通常会在应用程序启动时加载到IOC容器。例如,在一个典型的Spring Boot应用程序的入口类,使用@SpringBootApplication注解标记了应用程序的主类,并使用@MapperScan注解指定了需要扫描的Mapper接口所在的包。在main方法,通过调用SpringApplication.run方法来启动应用程序,并将主类和命令行参数传递给它。在运行过程Spring Boot会自动扫描应用程序的注解和配置,并将相应的Bean加载到IOC容器。 总的来说,Spring Boot源码分析涉及到Spring Boot的核心类和方法,以及它提供的各种机制和配置方式。通过深入研究这些源码,可以更好地理解Spring Boot的工作原理和内部机制。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [springboot源码分析](https://blog.csdn.net/xiaoxiaoyeyaya/article/details/108560836)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [SpringBoot源码分析](https://blog.csdn.net/mutf7/article/details/119387639)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值