본문 바로가기
프로그래밍/Spring

Spring / 외부 파일을 이용한 설정 - Environment 객체

by 소소로드 2018. 4. 8.

[외부 파일을 이용한 설정]

: Environment 객체 이용해서 외부의 설정 값을 가져와 이용

Environment의 사전적 정의 - 1. (주변의) 환경 2. (자연) 환경 3. 환경(컴퓨터, 사용자, 프로그램을 포함한 모든 것)



필요성

Environment 외부 설정------------->자바 클래스

(DB나 id/pass등 정보들)


- 요점은 외부의 설정 파일이 따로 있어서 수정 할 때 자바 클래스 수정없이 외부에서만 수정하면 된다.



순서

Context------------->Environment------------->PropertySources


1. 어플리케이션의 기초인 ConfigurableApplicationContext로 ctx 파일 생성


2. ctx.getEnvironment을 통해 얻은 객체를 ConfigurableEnvironment에서 생성한 Environment 객체 env에 담는다.


3. env.getPropertySources();로 프로퍼티소스를 얻어와서 MutablePropertySources에서 생성한 인스턴스에 넣는다.

   getPropertySources();를 해주는 이유는 Environment 객체 안에는 

   각각의 정보를 갖고있는 PropertySources라는 객체가 있어서 다 구해오는 것. 

   요청만 하면 그게 id든 pass든 db든 알아서 가지고 온다고 한다.


   (Environment - PropertySources(id,pass

                - PropertySources(db).... 이런식으로)


4. PropertySources에서 추가와 추출 가능 (추가 : addLast  / 추출 : getProperty)



*

어차피 글만 보고 이해하기란 당연히 쉽지 않으니 이론이 이렇다 하는 것만 알아두고

예제를 하면서 다시 보면 쉬울 것이다.



ConfigurableApplicationContext

ConfigurableEnvironment

----------------------------------------------------------------------------------------------------------


admin.properties

1
2
admin.id=admin
admin.pw=12345
cs

*

아이디, 비밀번호 설정값




ctx_AdminExample.xml

1
<bean id="adminConnection" class="com.yul.ex03_example.AdminConnection"/>
cs

*

AdminConnection에 대한 객체 생성





MainClass.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class MainClass {
 
    public static void main(String[] args) {
 
        ConfigurableApplicationContext ctx = new GenericXmlApplicationContext();
        ConfigurableEnvironment env = ctx.getEnvironment(); // ctx.getEnvironment();   
        MutablePropertySources propertySources = env.getPropertySources(); // env.getPropertySources();
        
        try {
            propertySources.addLast(new ResourcePropertySource("classpath:admin.properties")); // 추가 : propertySources.addLast 
            System.out.println(env.getProperty("admin.id")); // 추출 : env.getProperty
            System.out.println(env.getProperty("admin.pw"));
        } catch (IOException e) {
            e.getMessage();
        }
        
        GenericXmlApplicationContext gctx = (GenericXmlApplicationContext)ctx;
        gctx.load("classpath:ctx_AdminExample.xml");
        gctx.refresh(); // afterPropertiesSet()
        
        AdminConnection adminConnection = gctx.getBean("adminConnection", AdminConnection.class);
        System.out.println("admin Id = " + adminConnection.getAdminId());
        System.out.println("admin pw = " + adminConnection.getAdminpw());
        
        gctx.close();
        ctx.close(); // destroy() 
 
    }
}
 
cs

*

맨 위에 써놓은 순서를 되짚어 보고 

MainClass와 AdminConnection.java를 번갈아보면서 해석해보자.



ConfigurableApplicationContext ctx = new GenericXmlApplicationContext();

1. 어플리케이션의 기초인 ConfigurableApplicationContext로 ctx 파일 생성



ConfigurableEnvironment env = ctx.getEnvironment(); 

2. ctx.getEnvironment을 통해 얻은 객체를 ConfigurableEnvironment에서 생성한 Environment 객체 env에 담는다.



MutablePropertySources propertySources = env.getPropertySources(); 

3. env.getPropertySources();로 프로퍼티소스를 얻어와서 MutablePropertySources에서 생성한 인스턴스에 넣는다.


   getPropertySources();를 해주는 이유는 Environment 객체 안에는 각각의 정보를 갖고있는 PropertySources라는 

   객체가 있어서 다 구해오는 것. 요청만 하면 그게 id든 pass든 db든 알아서 가지고 온다고 한다.


propertySources.addLast(new ResourcePropertySource("classpath:admin.properties"));

System.out.println(env.getProperty("admin.id")); 

System.out.println(env.getProperty("admin.pw"));

4. addLast을 통해 admin.properties를 추가했고 getProperty를 통해 그 안에 있는 admin.id와 admin.pw를 추출했다.


여기까지의 결과는


admin

12345




*

그 이후에는 그동안 배웠던 내용과 같다. 


GenericXmlApplicationContext gctx = (GenericXmlApplicationContext)ctx;

gctx.load("classpath:ctx_AdminExample.xml");

gctx.refresh(); 

- Environment에 관한 내용이 담긴 ctx를 형변환하여 gctx 객체에 담고

  xml파일을 로드하고, 초기화 작업을 한다.    



AdminConnection adminConnection = gctx.getBean("adminConnection", AdminConnection.class);

System.out.println("admin Id = " + adminConnection.getAdminId());

System.out.println("admin pw = " + adminConnection.getAdminpw());

- ★이 부분이 중요할 것 같다.

   xml파일에서 adminConnection을 getBean했는데 

   그동안 배운대로 라면 xml과 AdminConnection.java를 매핑하는 부분에서


  private Environment env;

  private String adminId;

  private String adminpw;


   이 필드를 property로 묶어줘야 맞는것 아닐까?

   그런데 xml에는 Bean밖에 없고 코드에서는 자연스럽게 getAdminId, getAdminpw를 해주고 있다.


비밀은 앞선 4번 설명 코드에서 addLast를 통해 외부 파일의 프로퍼티 소스를 추가했고, 추출을 통해

env.getProperty("admin.id")와 env.getProperty("admin.pw") 이 값을 도출했기 때문이다.

이미 admin.properties 안에서 원하는 값을 뽑아냈다고 해야하나.





AdminConnection.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class AdminConnection implements EnvironmentAware, InitializingBean, DisposableBean {
 
    private Environment env;
    private String adminId;
    private String adminpw;
 
 
    @Override
    public void destroy() throws Exception {
        System.out.println("destroy() 실행");
    }
 
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("afterPropertiesSet() 실행");
        setAdminId(env.getProperty("admin.id")); // Environment객체에 속한 메서드 - getProperty
        setAdminpw(env.getProperty("admin.pw"));
    }
    
    @Override
    public void setEnvironment(Environment env) {
        System.out.println("setEnvironment() 실행");
        setEnv(env);
    }
 
    
    public Environment getEnv() {
        return env;
    }
 
    public void setEnv(Environment env) {
        this.env = env;
    }
 
    public String getAdminId() {
        return adminId;
    }
 
    public void setAdminId(String adminId) {
        this.adminId = adminId;
    }
 
    public String getAdminpw() {
        return adminpw;
    }
 
    public void setAdminpw(String adminpw) {
        this.adminpw = adminpw;
    }
    
}
cs

*

InitializingBean와 DisposableBean은 지난 시간 빈 생명주기에서 했으니 패스,


EnvironmentAware를 구현하면 setEnvironment가 오버라이딩되는데

이 의미는 빈이 생성되는 시점에 그 누구보다 가장 먼저 호출이 된다.


그리고 setEnv(env);를 써주는데 

이 env가 바로 MainClass파일에 4번 설명 부분에서 추출한 값이다.


setEnvironment가 실행될 때는 빈이 생성되는 시점이므로

getProperty 하고 값을 뽑아낸 직후 getBean을 하니까 자연스럽게 값이 나오는 것이다.


env은 매개변수를 따라 올라가고 매개변수는 set으로 들어가고

this.env를 통해 필드값 env로 들어간다.



*

결과


admin

12345


setEnvironment() 실행

afterPropertiesSet() 실행

admin Id = admin

admin pw = 12345


destroy() 실행