第 02 章 Spring Boot 基础配置

前言

当前环境,JDK1.8,IDEA2019.3,Maven3.6

Application.Properties

spring-configuration-metadata.json效果

在这里插入图片描述
可以看到根据前缀,idea自动给出了提示,并提供了一个默认值.
在这里插入图片描述

提示的来源则是jar包下的spring-configuration-metadata.json文件,支持的IDE会根据这个文件在输入时给予提示

spring-configuration-metadata.json生成

而spring-configuration-metadata.json文件的来源则分为两种

官方说明Configuration Metadata

1.根据@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)注解提供生成
2.手动按格式编写json

1.通过解析 @ConfigurationProperties 注解配置

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {

	/**
	 * Server HTTP port.
	 */
	private Integer port;

2.通过按格式手写

    {
      "name": "spring.banner.image.bitdepth",
      "type": "java.lang.Integer",
      "description": "The bit depth to use for ANSI colors. Supported values are 4 (16 color) or 8 (256 color).",
      "defaultValue": 4
    },
    {
      "name": "spring.banner.image.height",
      "type": "java.lang.Integer",
      "description": "Height of the banner image in chars (default based on image height)."
    },

1.赋值(默认值)
在这里插入图片描述
在这里插入图片描述

public abstract class AbstractConfigurableWebServerFactory implements ConfigurableWebServerFactory {

	private int port = 8080;

2.赋值(默认值)

    {
      "name": "spring.banner.image.bitdepth",
      "type": "java.lang.Integer",
      "description": "The bit depth to use for ANSI colors. Supported values are 4 (16 color) or 8 (256 color).",
      "defaultValue": 4
    },

BitDepth.FOUR;

org.springframework.boot.SpringApplication#printBanner
	private Banner printBanner(ConfigurableEnvironment environment) {
		if (this.bannerMode == Banner.Mode.OFF) {
			return null;
		}
		ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
				: new DefaultResourceLoader(getClassLoader());
				//打印类
		SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
		if (this.bannerMode == Mode.LOG) {
			return bannerPrinter.print(environment, this.mainApplicationClass, logger);
		}
		return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
	}
	
class SpringApplicationBannerPrinter {

	static final String BANNER_LOCATION_PROPERTY = "spring.banner.location";

	static final String BANNER_IMAGE_LOCATION_PROPERTY = "spring.banner.image.location";
...
	private BitDepth getBitDepthProperty(Environment environment) {
		Integer bitDepth = getProperty(environment, "bitdepth", Integer.class, null);
		//BitDepth.FOUR;
		return (bitDepth != null) ? BitDepth.of(bitDepth) : BitDepth.FOUR;
	}

可以看到 spring-configuration-metadata.json 作用只是给予提示,值的处理还是要自己做.

ConfigurationProperties

属性安全的注入变量,对于能转型的会帮忙转型,配置之后可以通过前缀在默认的application.properties文件中定义值.

@ConfigurationProperties(prefix = "user")
public class User {
    private String password;
    private String username;
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
}

HelloController

@RestController
@EnableConfigurationProperties(User.class)
public class HelloController {
    User user;
    public HelloController(User user) {
        this.user = user;
    }
    @GetMapping(value = "/hello")
    public User hello() {
        return user;
    }
}

除了通过 @EnableConfigurationProperties激活 @ConfigurationProperties,还可以直接在 @ConfigurationProperties注解的类上再加一个 @component,总之只要确保会被注册为bean,spring就会根据配置的注解信息自动注值
Spring处理

/**
 * {@link BeanPostProcessor} to bind {@link PropertySources} to beans annotated with
 * {@link ConfigurationProperties @ConfigurationProperties}.
 *
 * @author Dave Syer
 * @author Phillip Webb
 * @author Christian Dupuis
 * @author Stephane Nicoll
 * @author Madhura Bhave
 * @since 1.0.0
 */
public class ConfigurationPropertiesBindingPostProcessor
		implements BeanPostProcessor, PriorityOrdered, ApplicationContextAware, InitializingBean {

在这里插入图片描述

application.properties

spring.main.banner-mode=off
user.password=1
user.username=username

在这里插入图片描述

注意一定要有get,set方法和默认的构造方法,不然是无法注入值的.这是一种遵守Java语法的注值方式,没有通过反射强制赋值

@ConfigurationProperties(prefix = "user")
public class User {
    private String password;
    private String username;

    public User(String password, String username) {
        this.password = password;
        this.username = username;
    }
}

报错

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-12-01 00:48:33.961 ERROR 16480 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in com.example.note.User required a bean of type 'java.lang.String' that could not be found.


Action:

Consider defining a bean of type 'java.lang.String' in your configuration.


通过这个可以看到是根据propertysource注值的,所以也可以这样:

@ConfigurationProperties(prefix = "user")
public class User {
    private String password;
    private String username;
    public String getPassword() {
        return password;
...
}
@RestController
@EnableConfigurationProperties(User.class)
public class HelloController {
    User user;
...
}
@SpringBootApplication
@PropertySource("classpath:test.properties")
public class NoteApplication {
    public static void main(String[] args) {
        SpringApplicationBuilder builder = new SpringApplicationBuilder(NoteApplication.class);
        builder.build(args).run();
    }
}

在这里插入图片描述
在这里插入图片描述
注意,如果通过 @EnableConfigurationProperties(User.class),注入, @PropertySource(“classpath:test.properties”) 注解就一定要在启动类上,因为启动类上配置会默认一开始就加载解析,如果和User.class放在一起,registerBeanDefinitions不会处理扩展配置@PropertySource(“classpath:test.properties”)

@Import(EnableConfigurationPropertiesRegistrar.class)
public @interface EnableConfigurationProperties {
...
}
class EnableConfigurationPropertiesRegistrar implements ImportBeanDefinitionRegistrar {

	@Override
	public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
		registerInfrastructureBeans(registry);
		ConfigurationPropertiesBeanRegistrar beanRegistrar = new ConfigurationPropertiesBeanRegistrar(registry);
		getTypes(metadata).forEach(beanRegistrar::register);
	}

但是如果在User.class上加 @Component ,就可以直接添加 **@PropertySource(“classpath:test.properties”)**了,因为这样就会处理注解上面的外部化配置了,同时 **@EnableConfigurationProperties(User.class)**也可以删除了,虽然不影响,但是功能重复了

@ConfigurationProperties(prefix = "user")
@Component
@PropertySource("classpath:test.properties")
public class User {
    private String password;
    private String username;
    public String getPassword() {
    }
    ....
 }
 @RestController
public class HelloController {
    User user;
    public HelloController(User user) {
        this.user = user;
    }
    ...
}
@SpringBootApplication
public class NoteApplication {
    public static void main(String[] args) {
        SpringApplicationBuilder builder = new SpringApplicationBuilder(NoteApplication.class);
        builder.build(args).run();
    }
}

在这里插入图片描述

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页