網頁

2020/9/24

Spring Boot @ConfigurationProperties with @ConstructorBinding

Spring使用@ConfigurationProperties@ConstructorBinding將properties檔內容以建構式注入到bean。

Spring Boot 使用@ConfigurationProperties 綁定properties至Bean中是透過setter的方式注入properties,但這樣bean的屬性無法以final修飾因此能被修改,因此本篇改用建構式注入的方式才能加上final並達到immutable的效果。

注意@ConstructorBinding在Spring Boot 2.2.0版本之後才有。

範例環境:

  • Java 8
  • Spring Boot 2.3.2.RELEASE
  • Maven
  • Lombok

system.properites為要注入bean的properties檔。

system.properties

system.name=Demo system
system.version=1.0.0
system.url=192.168.0.111
system.port=8080

注入system.properites內容的bean,在類別名稱前加上@ConfigurationProperties,屬性prefix設定key的前綴。加上@ConstructorBinding才能以建構式注入對應的properties值。

注意@ConstructorBinding不能與由@Component@Bean@Import的bean一起使用,Spring改以@EnableConfigurationProperties@ConfigurationPropertiesScan來註冊這些constructor binding的bean。

SystemProperties

package com.abc.demo.properties;

import lombok.Getter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;

@Getter
@ConstructorBinding
@ConfigurationProperties(prefix = "system")
public class SystemProperties {

    private final String name;    // system.name
    private final String version; // system.version
    private final String url;     // system.url
    private final String port;    // system.port

    public SystemProperties(
            String name,
            String version,
            String url,
            String port) {
        this.name = name;
        this.version = version;
        this.url = url;
        this.port = port;
    }

}

在配置類設定@PropertySource指定classpath下的system.properties。加上@EnableConfigurationProperties指定要註冊為bean的@ConstructorBinding的類,也就是上面的SystemProperties;或使用@ConfigurationPropertiesScan掃描所在package下的@ConstructorBinding的類來註冊。

DemoApplication

package com.abc.demo;

import com.abc.demo.properties.SystemProperties;
import com.abc.demo.service.DemoService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.PropertySource;

@EnableConfigurationProperties(SystemProperties.class)
//@ConfigurationPropertiesScan
@PropertySource("classpath:system.properties")
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {

        ApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);
        DemoService demoService = ctx.getBean(DemoService.class);

        demoService.printSystemPropertiesValue();

    }

}

DemoApplication.main()中調用的DemoService是一般的@Component(@Service)bean。可以看到SystemProperties雖非@Component註冊的bean,但仍可透過@Autowired注入。

DemoService

package com.abc.demo.service;

import com.abc.demo.properties.SystemProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DemoService {

    @Autowired
    SystemProperties systemProperties;

    public void printSystemPropertiesValue() {
        System.out.println(systemProperties.getName());
        System.out.println(systemProperties.getVersion());
        System.out.println(systemProperties.getUrl());
        System.out.println(systemProperties.getPort());
    }
}

啟動專案印出結果。

Demo system
1.0.0
192.168.0.111
8080

參考github


沒有留言:

張貼留言