Spring - Bean과 ioc에 대해서 (예제 코드)

스프링에서 객체를 직접관리하는데 그렇게 직접관리 되는 객체를 bean라 하고

그 bean들이 관리되는 장소가 Spring Container인 것이다.

 


그리고 Spring Container가 이렇게 객체들을 제어하는 권한을 개발자로부터 가져갔기 때문에

ioc(제어역전현상)이라고 말한다.

 

 

다음의 예제 코드를 살펴보자.

먼저 iocSpring이라는 웹앱의 예제코드이다.

(설명은 주석으로 작성함)

 

1.iocSpringApplication.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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.example.ioc_spring;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
import java.util.Base64;
import java.util.stream.BaseStream;
 
@SpringBootApplication // @SpringBootApplication 이라는 어노테이션을 붙임으로써 이 앱자체가 스프링부트로 동작하게끔 한다.
public class IocSpringApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(IocSpringApplication.class, args);
 
        //1. ApplicationContext로 Bean을 가져오기 (bean 등록안한 상태)
        ApplicationContext context = ApplicationContextProvider.getContext();
 
//        Base64Encoder base64Encoder = context.getBean(Base64Encoder.class); // bean등록을 안했기에 이렇게 class명으로 bean가져오게 된다.
//        UrlEncoder urlEncoder = context.getBean(UrlEncoder.class);
 
//        Encoder encoder = context.getBean(Encoder.class);
//        String result = encoder.encode(url);
//        System.out.println(result);
 
 
 
        // 2. Configuration에 여러개 bean을 등록하고 bean 이름과 class로 가져오기
        String url = "www.naver.com/books/it?page=10&size=20&name=spring-boot";
 
        Encoder encoder2 = context.getBean("base64Encode", Encoder.class); // bean 등록을 했기에 이제 앞에 어떤 bean인지 이름을 써주고 클래스명을 써준다.
        String result2 = encoder2.encode(url);
        System.out.println(result2);
 
        Encoder encoder3 = context.getBean("urlEncode", Encoder.class);
        String result3 = encoder3.encode(url);
        System.out.println(result3);
 
//        Encoder encoder = new Encoder(base64Encoder);
 
//        String result = encoder.encode(url);
//        System.out.println(result);
 
//        encoder.setIEncoder(urlEncoder);
//        result = encoder.encode(url);
//        System.out.println(result);
    }
 
}
 
@Configuration // 한개의 클래스에서 여러개의 bean을 등록할때 사용하는 어노테이션
class Appconfig{
    @Bean("base64Encode"//Encoder라는 동일한 자료형의 객체이니까Bean 어노테이션에서 이름을 붙여주도록 한다.
    public Encoder encoder(Base64Encoder base64Encoder){
        return new Encoder(base64Encoder);
    }
 
    @Bean("urlEncode"// urlEncoder라는 명이 이미등록되어있어서 de로
    public Encoder encoder(UrlEncoder urlEncoder){
        return new Encoder(urlEncoder);
    }
    // 이처럼 스프링 컨테이너 안에서 여러가지 Bean들을 담아서 관리할 수 있다.
}
cs

 

2. IEncoder.java (인터페이스)

1
2
3
4
5
6
package com.example.ioc_spring;
 
public interface IEncoder {
    String encode(String message);
 
}
cs

 

3. Encoder.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
package com.example.ioc_spring;
 
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
 
@Component
public class Encoder {
    private IEncoder iEncoder; // 추상화시키기 위해서 IEncoder 객체를 필드로 사용
 
    public Encoder(@Qualifier("base74Encoder") IEncoder iEncoder){ //Qualifier로 컴포넌트의 이름을 바꾸어줄 수 있다.
        //this.iEncoder = new Base64Encoder();  // 만약 Base64Encoder가아닌 urlencoding을 요청할 경우 이렇게 기본생성자를 또 바꿔줘야하는 굉장히 비효율적이고 본질적인 문제점이 존재한다.
        // 그런데 여기에 DI라는 개념을 도입하면 기본생성자를 건들지 않아도 충분히 이 객체를 재활용할 수 있다.
        // 외부에서 내가 사용할 객체를 주입시켜주는 개념이기 때문에 가능한 것이다.
        //this.iEncoder = new UrlEncoder();
 
        // 그렇게 하기위해서는 생성자에서 매개변수를 받아줘야한다.
 
        //최종적으로 ioc개념을 위해서는 아래와 같이 작성한다.
        this.iEncoder = iEncoder;
    }
 
    public void setIEncoder(IEncoder iEncoder){
        this.iEncoder=  iEncoder;
    }
 
    public String encode(String message){
        return iEncoder.encode(message);
    }
 
}
cs

 

4. Base64Encoder.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.example.ioc_spring;
import org.springframework.stereotype.Component;
 
import java.util.Base64;
 
@Component("base74Encoder"// 이 Base64Encoder라는 클래스는 스프링에서 관리를 해줘~ bean으로 만들어서 스프링 너가 관리해 라는 의미
          // 이렇게 Component 어노테이션을 붙이면 스프링이 실행이 될 때 이 Component 어노테이션이 붙은 클래스를 찾아서
          // 직접 객체를 싱글톤 형태로 만들어서 스프링 컨테이너에서 관리를 하게된다.
          // 이 때 어떻게 컨테이너에서 원하는 객체를 꺼내서 쓸까? -> SpringApplicationContext라는 객체를 통해서!
          // SpringApplicationContext에 대한 코드들은 인터넷에 굉장히 많이 널려있다.
public class Base64Encoder implements IEncoder{
    public String encode(String message){
        return Base64.getEncoder().encodeToString(message.getBytes());
    }
}
cs

 

 

5. UrlEncoder.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.example.ioc_spring;
 
import org.springframework.stereotype.Component;
 
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
 
@Component
public class UrlEncoder implements IEncoder{ // 인터페이스를 상속
 
    public String encode(String message){
        try {
            return URLEncoder.encode(message, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }
}
cs

 

 

'Spring' 카테고리의 다른 글

Spring - Junit Test  (0) 2022.01.17
Spring - Component vs Bean vs Configuration  (0) 2022.01.12
Spring - DI (의존성 주입) 이란 무엇인가?  (0) 2022.01.11
Spring - 왜 Spring을 쓰는가?  (0) 2022.01.11
Spring - ObjectMapper  (0) 2022.01.11