模拟Springboot的自动配置

x33g5p2x  于2021-03-14 发布在 Spring  
字(5.3k)|赞(0)|评价(0)|浏览(129)

Springboot提供了很多的自动配置,当你创建一个SpringBoot项目后,你可以如下找到它自动做了哪些配置:


spring.factories中有很多看不懂的配置,我们来选择下面的源码看一下:

org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration

这个配置是与设置字符集相关,它的部分源码如下:

// 读取配置文件的类
@Configuration(
    proxyBeanMethods = false
)
// 将ServerProperties.class加载到当前的类中
@EnableConfigurationProperties({ServerProperties.class}) 
// 判断当前的项目是否为Web项目,是则让当前的配置类生效
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
// 判断CharacterEncodingFilter.class是否存在,如果存在则加载到当前类中
@ConditionalOnClass({CharacterEncodingFilter.class}) 
// 读取配置文件中以server.servlet.encoding为前缀的属性的属性值
// 该属性的默认值为enabled
// matchIfMissing=true 不管配置文件中是否存在prefix,一律让
// 当前配置类生效
@ConditionalOnProperty(
    prefix = "server.servlet.encoding",
    value = {"enabled"},
    matchIfMissing = true
)
// 设置编码的核心类
public class HttpEncodingAutoConfiguration {
    private final Encoding properties;
...
// 将方法的返回值作为<bean class="返回的返回值"/>
// 将方法名作为<bean id="方法名"/>
@Bean
// 如果CharacterEncodingFilter没有被注入Spring的IoC容器,则注入
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {
    CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
    filter.setEncoding(this.properties.getCharset().name());
    filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.REQUEST));
    filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.RESPONSE));
    return filter;
}

下面我们来模拟一下SpringBoot的自动配置过程,创建如下三个类:

SayHelloAutoConfiguration:
    将SayHelloServer和SayHelloProperties加载到SayHelloAutoConfiguration,
    调用自身的sayHelloServer()方法将SayHelloServer类注入到IoC容器中。
SayHelloServer:
    提供一个message属性待注入;
SayHelloProperties:
    提供一个message属性,将它的值注入到SayHelloServer的message属性中;

步骤如下:
1. 新建一个名为likeautoconfig的Maven项目




2. 添加下面的配置到pom.xml文件中
pom.xml

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-autoconfigure -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-autoconfigure</artifactId>
      <version>2.2.9.RELEASE</version>
    </dependency>
  </dependencies>

3. 创建三个Java类
org/example/demo/SayHelloProperties.java

package org.example.demo;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "hello")
public class SayHelloProperties {

    // 如果你在application.properties中编写了 hello.message
    // 则会覆盖这里的message
    private String message = "spring boot!";

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

org/example/demo/SayHelloServer.java

package org.example.demo;

public class SayHelloServer {

    private String message;

    public String sayHelloServer(){
        return "hello " + message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

org/example/demo/SayHelloAutoConfigration.java

package org.example.demo;

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;

/**
 * 该类调用sayHelloServer()方法将SayHelloProperties.message="spring boot"赋值给
 *      SayHelloServer.message,然后SayHelloServer类调用它的sayHelloServer方法将字符串拼接成
 *      "hello spring boot",也就是说SayHelloAutoConfigration自动将SayHelloProperties的属性值
 *      自动配给了SayHelloServer的message属性,这就是自动配置。
 */
@Configuration
@EnableConfigurationProperties(SayHelloProperties.class)
@ConditionalOnClass(SayHelloServer.class)
@ConditionalOnProperty(prefix = "hello",value = "enabled",matchIfMissing = true)
public class SayHelloAutoConfiguration {

    @Resource
    private SayHelloProperties sayHelloProperties;

    @Bean
    @ConditionalOnMissingBean
    public SayHelloServer sayHelloServer(){
        SayHelloServer sayHelloServer = new SayHelloServer();
        sayHelloServer.setMessage(sayHelloProperties.getMessage());
        return sayHelloServer;
    }
}

4. 将我们自定义的SayHelloAutoConfiguration自动插件加入到spring.factories文件中
resources/META-INF/spring.factories

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.example.demo.SayHelloAutoConfiguration

5. install项目

6. 新建一个名为testlikeautoconfig的SpringBoot项目用于测试





6. 将上面创建的likeautoconfig项目作为testlikeautoconfig项目的依赖




7. 编写测试类
com/example/testlikeautoconfig/HelloController.java

package com.example.testlikeautoconfig;

import org.example.demo.SayHelloServer;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;

@Controller
public class HelloController {
    @Resource
    private SayHelloServer sayHelloServer;

    @RequestMapping(value = "/hello")
    @ResponseBody
    public String sayHello() {
        return sayHelloServer.sayHelloServer();
    }
}

8. 在application.properties中添加如下属性
resources/application.properties

hello.message=springboot auto configuration test!

9. 启动SpringBoot项目进行测试
启动项目后访问:http://localhost:8080/hello 页面显示如下:

可以看到成功获取了配置文件的值。

相关文章

热门文章

更多