본문으로 건너뛰기

@Value를 Constructor와 함께 사용할 때

@Value값이 필드멤버로 있고 생성자가 있을때에 생성자가 먼저 생성된 후, 후순번으로 injection된다.
즉, 스프링부트에서는 인젝션 순서가 생성자 -> value 이므로.. 다음과 같은 코드에서는 생성자가 생성될때 value가 null로 들어간다

@Named("dbOneConfig")
public class FirstDB implements Config {

private final DataSource dataSource;

private static final FirstDB FIRST_DB = new FirstDB();

private Dialect dialect = new MysqlDialect();

@Value("${dbOne.dataSourceClassName}")
private String dataSourceClassName;

@Value("${dbOne.serverName}")
private String serverName;

@Value("${dbOne.port}")
private String port;

@Value("${dbOne.databaseName}")
private String databaseName;

@Value("${dbOne.username}")
private String username;

@Value("${dbOne.password}")
private String password;

@Value("${dbOne.maximumPoolSize}")
private int maximumPoolSize;

@Value("${dbOne.maximumPoolSize}")
private int minimumIdle;

@Value("${dbOne.catalog}")
private String catalog;

private FirstDB(){
HikariConfig config = new HikariConfig();
config.setDataSourceClassName(dataSourceClassName);
config.addDataSourceProperty("serverName", serverName);
config.addDataSourceProperty("port", port);
config.addDataSourceProperty("databaseName", databaseName);
config.setUsername(username);
config.setPassword(password);
config.setMaximumPoolSize(maximumPoolSize);
config.setMinimumIdle(minimumIdle);
config.setCatalog(catalog);
HikariDataSource ds = new HikariDataSource(config);

this.dataSource = ds;

return dataSource;
}

@Override
public DataSource getDataSource() {

return this.dataSource;
}

@Override
public Dialect getDialect() {
return dialect;
}

public static FirstDB singleton() { return FIRST_DB; }
}

싱글톤을 사용하기 위해서 FirstDB클래스와 같은이름의 FirstDB함수에 데이터 소스 내용을 박아넣고
안쪽의 데이터소스들은 value값을 참조한다. 그런데 여기서 스프링부트의 인젝션 우선순위 라는것이 있어서
생성자가 만들어질때 null로 만들어지게 된다는 것이다.

그래서 일단.... 요런 코드로 바꿔 썼다. (잘 작동한다.)

생성자가 생성될때 파라미터를 받아서 생성하도록 하고, 파라미터값을 value로 해줬다.

@Named("dbOneConfig")
public class FirstDB implements Config {

private final DataSource dataSource;

private static final FirstDB FIRST_DB = new FirstDB();

private Dialect dialect = new MysqlDialect();

private FirstDB(
@Value("${dbOne.dataSourceClassName}") String dataSourceClassName,
@Value("${dbOne.serverName}") String serverName,
@Value("${dbOne.port}") String port,
@Value("${dbOne.databaseName}") String databaseName,
@Value("${dbOne.username}") String username,
@Value("${dbOne.password}") String password,
@Value("${dbOne.maximumPoolSize}") int maximumPoolSize,
@Value("${dbOne.maximumPoolSize}") int minimumIdle,
@Value("${dbOne.catalog}") String catalog
){
HikariConfig config = new HikariConfig();
config.setDataSourceClassName(dataSourceClassName);
config.addDataSourceProperty("serverName", serverName);
config.addDataSourceProperty("port", port);
config.addDataSourceProperty("databaseName", databaseName);
config.setUsername(username);
config.setPassword(password);
config.setMaximumPoolSize(maximumPoolSize);
config.setMinimumIdle(minimumIdle);
config.setCatalog(catalog);
HikariDataSource ds = new HikariDataSource(config);

this.dataSource = ds;

return dataSource;
}

@Override
public DataSource getDataSource() {

return this.dataSource;
}

@Override
public Dialect getDialect() {
return dialect;
}

public static FirstDB singleton() { return FIRST_DB; }
}

위의 경우에는 컨넥션 설정을 싱글톤으로 해야해서 저런식으로 코드작성을 하였는데,
싱글톤이 아닌 경우에는 아래와 같은 방법으로 사용할 수 있다.

@Configuration 에서 빈을 등록

@Configuration
public class AppConfig {
@Value("${sample.id}")
private Integer id;

@Value("${sample.name}")
private String name;

@Bean
SampleService sampleService() {
return new SampleService(id, name, new SampleObject());
}
}

위에처럼 @Configuration을 이용해서 value로 받은것들을 빈으로 등록해주고

사용을 이렇게!

public class SampleService {
private Integer id;

private String name;

private final SampleObject sampleObject;

/**
* 생성자
*/
public SampleService(Integer id, String name, SampleObject sampleObject) {
this.id = id;
this.name = name;
this.sampleObject = sampleObject;
this.sampleObject.setId(id);
this.sampleObject.setName(name);
}

public void print() {
System.out.println("id = " + id);
System.out.println("name = " + name);
System.out.println("sampleObject.id = " + sampleObject.getId());
System.out.println("sampleObject.name = " + sampleObject.getName());
}
}