IoC(Inversion of Controller)

  • IoC: "제어의 역전"(=역제어)라는 의미로, 메서드나 객체의 호출을 개발자가 하지 않고 외부에서 호출하는 것
    • 객체의 의존성을 역전시켜 객체간의 결합도를 줄이고 유연한 코드를 작성할 수 있게 하며, 가독성 향상코드 중복 축소, 편한 유지 보수 등의 장점이 있다.
  • 순제어: Student student = new Student(); 와 같이 개발자가 직접 객체를 호출한다.
  • 역제어: 스프링 컨테이너가 빈으로 등록한 객체들을 생성 및 관리한다.
    • @Component, @Bean을 사용해서 빈으로 등록할 수 있다.
    • XML 파일에서는 <bean> 태그를 사용하여 빈으로 등록할 수 있다.

 


IoC 컨테이너 분류 체계

 

IoC에는 크게 DL(Dependency Lookup)DI(Dependency Injection)이 있다.

 

 


DL(Dependency Lookup)

  • "의존성 검색"이라는 의미로, Bean에 접근하기 위해 컨테이너가 제공하는 API를 이용하여 Bean을 Lookup하는 것
  • 컨테이너가 제공하는 API를 이용할 때 의존관계와 종속성 문제가 발생하는데, 이를 줄이는 방법으로 DI를 사용한다.

 

DI(Dependency Injection)

  • "의존성 주입"이라는 의미로, 각 클래스 간의 의존성을 자신이 아닌 외부(컨테이너)에서 주입하는 것
  • 컨테이너가 의존관계를 자동으로 연결해주기 때문에 개발자들이 컨테이너 API에 종속되지 않는다.
    1. Setter Injection: setter 메서드를 이용하여 클래스 간의 의존관계를 연결하는 방법
    2. Constructor Injection: 생성자를 이용하여 클래스 간의 의존관계를 연결하는 방법
    3. Method Injection: Singleton(오직 하나의 객체만 생성되는 패턴) 객체와 Non-Singleton 객체 간의 연결이 필요한 경우 사용하는 방식

자바로 프로그래밍을 하면서 객체를 생성할 때 직접 클래스에 new 연산자를 이용하여 생성하였다. 하지만 DI는 개발자가 직접 코딩을 하여 객체를 생성하는 것이 아니라, 컨테이너(IoC)가 이를 생성시켜 주는 것이다. 그렇게 되면 코드에서 직접적인 연관관계가 발생하지 않아 각 클래스들의 변경이 자유로워지는데, 이를 느슨한 결합이라고 한다.

 

각 클래스 간의 결합도가 높으면 유지보수가 힘들어진다. 따라서 각 클래스 간의 연관관계를 클래스 내에서 맺어주는 것이 아니라 스프링 자체에서 설정을 통해 맺어줌으로써 결합도를 낮춰준다.

 

스프링에서는 의존관계를 설정하는 xml 파일에서 각각의 클래스 객체를 <bean> 태그로 표시한다.

<bean> 태그의 속성 설명
id 빈 객체의 고유 이름으로, 이를 이용하여 빈에 접근하며 중복되어서는 안 된다.
name 빈 객체의 별칭
class 생성할 클래스 이름 (빈 객체를 주입할 클래스 이름)
constructor-arg 생성자를 이용해 값을 주입할 때 사용한다.
property setter를 이용해 값을 주입할 때 사용한다.

 

이러한 Bean 설정 파일을 바탕으로 의존관계를 확인하여 주입한다.

이는 객체 레퍼런스를 컨테이너로부터 주입 받아서 실행시에 동적으로 의존관계가 생성되는 것이다.

따라서 컨테이너(IoC)가 흐름의 주체가 되어 어플리케이션 코드에 의존관계를 주입하게 된다.


객체 간의 의존관계 맺기

  1. ex01: 객체 간의 의존관계 맺기 (강한 결합력)
  2. ex02: 객체 간의 의존관계 맺기 - 의존관계를 약간 느슨하게 맺기 (약한 결합력)
  3. ex03: 객체 간의 의존관계 맺기 - 의존 설정을 스프링 컨테이너를 통해 설정함 => DL
  4. ex04: DI(Dependency Injection) - Setter Injection (xml 기반)
  5. ex05: DI(Dependency Injection) - Constructor Injection (xml 기반)
  6. ex06: xml이 아닌 Java 클래스를 이용해 빈을 생성하고 주입 (Java 기반)
  7. ex07: Java 클래스를 이용해 빈을 생성하되, 인젝션 어노테이션을 이용

ex01: 객체 간의 의존관계 맺기 (강한 결합력)

[Class] MessageBeanKo.java

1
2
3
4
5
6
7
8
package ex01;
 
public class MessageBeanKo {
    
    public void sayHello(String name) {
        System.out.println("안녕하세요? " + name + "님!!");
    }
}
cs

 

[Class] MessageBeanEn.java

1
2
3
4
5
6
7
8
package ex01;
 
public class MessageBeanEn {
    
    public void sayHello(String name) {
        System.out.println("Hello? " + name + "!!");
    }
}
cs

 

[Main Class] HelloApp.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package ex01;
 
public class HelloApp {
 
    public static void main(String[] args) {
        
        MessageBeanKo mb1 = new MessageBeanKo();
        MessageBeanEn mb2 = new MessageBeanEn();
        mb1.sayHello("홍길동");
        mb2.sayHello("Jason");
 
    }
 
}
cs

실행 결과

 

  • HelloApp이 MessageBeanKo, MessageBeanEn 객체를 사용(use)한다.
    • HelloApp이 MessageBeanKo, MessageBeanEn에 의존한다. (dependency)
    • 이때 의존성이 있는 객체들의 결합도가 중요하다.
  • 결합도가 강하면 향후 객체를 교환하고자 할 때 문제가 될 수 있다.
    • 의존성이 있는 객체들끼리는 결합도가 느슨한 것이 좋다.

ex02: 객체 간의 의존관계 맺기 - 의존관계를 약간 느슨하게 맺기 (약한 결합력)

[Interface] MessageBean.java

1
2
3
4
5
6
7
package ex02;
 
public interface MessageBean {
    
    public void sayHello(String name);
 
}
cs

 

[Class] MessageBeanKo.java

1
2
3
4
5
6
7
8
9
10
11
package ex02;
 
public class MessageBeanKo implements MessageBean {
 
    @Override
    public void sayHello(String name) {
        System.out.println("안녕?? " + name + "님!!");
 
    }
 
}
cs

 

[Class] MessageBeanEn.java

1
2
3
4
5
6
7
8
9
10
11
package ex02;
 
public class MessageBeanEn implements MessageBean {
 
    @Override
    public void sayHello(String name) {
        System.out.println("How are you?? " + name + "!!");
 
    }
 
}
cs

 

[Main Class] HelloApp.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package ex02;
 
public class HelloApp {
 
    public static void main(String[] args) {
        //부모는 자식을 담을 수 있다.
        //인터페이스 타입 변수 = 자식객체();
        MessageBean mb1 = new MessageBeanEn();
        MessageBean mb2 = new MessageBeanKo();
        mb1.sayHello("Peter");
        mb2.sayHello("홍길동");
        
    }
 
}
cs

실행 결과

 

객체 간의 결합력이 ex01에 비해 다소 느슨해졌다. HelloApp과 MessageBean 구현 객체 간의 의존성이 약하다.

 


ex03: 객체 간의 의존관계 맺기 - DL

DL: "의존성 검색"이라는 의미로, Bean에 접근하기 위해 컨테이너가 제공하는 API를 이용하여 Bean을 Lookup하는 것

 

[Interface] MessageBean.java

1
2
3
4
5
6
package ex03;
 
public interface MessageBean {
    //추상메서드 + 상수(public static final변수)
    public void sayHello(String name);
}
cs

 

[Class] MessageBeanKo.java

1
2
3
4
5
6
7
8
9
10
11
package ex03;
 
public class MessageBeanKo implements MessageBean {
 
    @Override
    public void sayHello(String name) {
        System.out.println("안녕?? " + name + "님!!");
 
    }
 
}
cs

 

[Class] MessageBeanEn.java

1
2
3
4
5
6
7
8
9
10
11
package ex03;
 
public class MessageBeanEn implements MessageBean {
 
    @Override
    public void sayHello(String name) {
        System.out.println("How are you?? " + name + "!!");
 
    }
 
}
cs

 

[XML] applicationContext.xml

Bean에 대한 정보가 있는 XML파일

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
    
    <bean id="mbKo" class="ex03.MessageBeanKo" scope="singleton"/> <!-- singleton이 default -->
    <bean id="mbEn" class="ex03.MessageBeanEn"/>
</beans>
cs

위와 같은 코드를 통해 MessageBeanKo, MessageBeanEn 클래스를 검색하여 가져올 수 있다.

 

[Main Class] HelloApp.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package ex03;
 
public class HelloApp {
 
    public static void main(String[] args) {
        //스프링 컨테이너를 통해 필요한 객체를 DL(Dependency Lookup)해보자
        String resource = "src/main/java/ex03/applicationContext.xml";
        
        //스프링 컨테이너 생성
        ApplicationContext ctx = new FileSystemXmlApplicationContext(resource);//스프링 컨테이너
        
        //필요한 객체를 찾는다
        MessageBean mb = (MessageBean)ctx.getBean("mbEn");//Lookup, 형변환
        mb.sayHello("이수지");
    }
 
}
cs

실행 결과

 


ex04: DI(Dependency Injection) - Setter Injection (xml 기반)

  • 선택적으로 의존성을 주입하고 싶을 경우 Setter Injection을 사용
  • 주입한 의존성에 대해 setter를 통해 변경이 가능
  • <property>: setter를 이용해 값을 주입할 때 사용
    • name= class에서 사용할 setter 이름 (setXXX)
    • ref= setter에 주입할 Bean(객체)의 이름

 

[Interface] MessageBean.java

1
2
3
4
5
6
7
8
package ex04;
 
public interface MessageBean {
    void sayHello();
    void sayHi(String ... names);
    //...은 매개변수를 받기는 하지만 몇 개인지 모른다는 의미
    //names는 String[] 배열 타입
}
cs

 

[VO] MessageBeanImpl.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
67
68
69
70
package ex04;
 
import java.util.*;
 
public class MessageBeanImpl implements MessageBean {
    
    //property: 멤버변수
    //default값: null <=프로퍼티값을 설정파일(appContext.xml)에서 넣어줄 예정(setter injection)
    private String greeting;
    private String name;
    private Date today;
    private Random ran;
    
    @Override
    public void sayHello() {
        System.out.println(greeting + " " + name + "^^");
        if(today!=null)
            System.out.println("오늘 날짜는: " + today.toString());
        System.out.println("---------------------------");
 
    }
 
    @Override
    public void sayHi(String... names) {
        System.out.println(greeting);
        if(names!=null) {
            for(String name:names) {
                System.out.print(name + ", ");
            }
        }
        System.out.println("\n******************");
        if(ran!=null)
            System.out.println("오늘의 행운의 숫자는: " + ran.nextInt(100));
    }
    //setter, getter
    public String getGreeting() {
        return greeting;
    }
 
    public void setGreeting(String greeting) {
        this.greeting = greeting;
        System.out.println("setGreeting(): " + greeting);
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Date getToday() {
        return today;
    }
 
    public void setToday(Date today) {
        this.today = today;
    }
 
    public Random getRan() {
        return ran;
    }
 
    public void setRan(Random ran) {
        this.ran = ran;
    }
    
}
cs

 

[설정파일] appContext.xml

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
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
 
    <!-- MessageBeanImpl 객체를 bean으로 등록. id는 mb1 -->
    <bean id="mb1" class="ex04.MessageBeanImpl"/>
    <!-- MessageBeanImpl mb1 = new MessageBeanImpl(); mb1의 프로퍼티에는 null값만 들어간다 -->
    
    <bean id="mb2" class="ex04.MessageBeanImpl">
        <property name="greeting">
            <value>환절기 감기 조심하세요~</value>
        </property> <!-- setProperty처럼 setter를 부름 -->
        <!-- mb2.setGreeting("환절기 감기 조심하세요~"); 와 동일 -->
        <property name="name" value="송하니"/>
        <!-- mb2.setName("송하니"); 와 동일 -->
        <property name="today">
            <ref bean="date"/>
        </property>
        <!-- mb2.setToday(date); -->
    </bean>
    
    <!-- Date객체를 빈으로 등록 -->
    <!-- Date date = new Date(); -->
    <bean id="date" class="java.util.Date"/>
    
    <!-- Random random = new Random(); -->
    <bean id="random" class="java.util.Random"/>
    
    <!-- [실습] mb3로 MessageBeanImpl 빈 등록하기
        이름과 인삿말 주입하기, 날짜, 랜덤숫자도 주입하기 -->
     <bean id="mb3" class="ex04.MessageBeanImpl">        
         <property name="greeting" value="오늘도 행복하세요~"/>
         <property name="name" value="공채연"/>
         <property name="today" ref="date"/>
         <property name="ran" ref="random"/>
     </bean>
</beans>
cs

 

[Main Class] HelloSpringApp.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 ex04;
 
public class HelloSpringApp {
 
    public static void main(String[] args) {
        //1. mb1을 찾아서 sayHello() 호출
        //스프링 컨테이너를 통해 필요한 객체를 DL(Dependency Lookup)해보자
        String resource = "src/main/java/ex04/appContext.xml";
                
        //스프링 컨테이너 생성
        ApplicationContext ctx = new FileSystemXmlApplicationContext(resource);//스프링 컨테이너
                
        //필요한 객체를 찾는다
        MessageBean mb1 = ctx.getBean("mb1", MessageBean.class);//강제 형변환
        //MessageBean mb1 = (MessageBean)ctx.getBean("mb1"); 과 동일
        mb1.sayHello();
        mb1.sayHi("BTS""뉴진스""르세라핌");
        
        //mb2를 찾아서 sayHello() 호출
        MessageBean mb2 = ctx.getBean("mb2", MessageBean.class);//강제 형변환
        mb2.sayHello();
        mb2.sayHi("빅뱅""소녀시대""원더걸스");
        
        //mb3를 찾아서 sayHello() 호출
        MessageBean mb3 = ctx.getBean("mb3", MessageBean.class);//강제 형변환
        mb3.sayHello();
        mb3.sayHi("김라라""최라라""이라라");
    }
 
}
cs

실행 결과

 


ex05: DI(Dependency Injection) - Constructor Injection (xml 기반)

  • 생성자를 통해 의존성을 주입하는 방식
  • <constructor-arg> 태그를 통해 값을 넣는다.
    • index: 생성자 몇 번째 인수에 값을 전달할 것인지 지정 (0부터 시작)
    • type: 생성자의 어떤 자료형 인수에 값을 전달할 것인지 지정
    • ref: 주입할 참조 객체를 지정
    • value: 주입할 값을 지정

 

[interface] Emp.java

1
2
3
4
5
6
7
package ex05;
 
public interface Emp {
    void info1();
    void info2();
    void info3();
}
cs

 

[VO] EmpImpl.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
package ex05;
 
import java.util.Date;
 
public class EmpImpl implements Emp {
    
    //property
    private String name;
    private int sal;
    private Date hiredate;
    
    public EmpImpl(String name, int sal, Date hdate) {
        this.name = name;
        this.sal = sal;
        this.hiredate = hdate;
    }
    public EmpImpl(String name, int sal) {
        this(name, sal, null);
    }
    public EmpImpl(String name) {
        this(name, 0null);
    }
    
    @Override
    public void info1() {
        System.out.println("name: " + name);
    }
 
    @Override
    public void info2() {        
        this.info1();
        System.out.println("salary: " + sal);
    }
 
    @Override
    public void info3() {
        this.info2();
        System.out.println("hiredate: " + hiredate);
    }
 
}
cs

 

[설정파일] emp.xml

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
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
    
    <!-- e1. 기본생성자가 없으므로 에러 발생 -->
    <!-- <bean id="e1" class="ex05.EmpImpl"></bean> -->
    
    <!-- e2. String 1개 (name)를 생성자를 통해 주입해보자 -->
    <bean id="e2" class="ex05.EmpImpl">
        <constructor-arg index="0" type="java.lang.String">
            <value>Scott</value>
        </constructor-arg>
    </bean>
    
    <!-- e3. name, 급여 생성자 통해 주입 -->
    <bean id="e3" class="ex05.EmpImpl">
        <constructor-arg index="0" type="java.lang.String" value="King"/>
        <constructor-arg index="1" type="int" value="5000"/>
    </bean>
    
    <!-- e4. name, sal, hiredate 주입 (index 생략 가능) -->
    <bean id="e4" class="ex05.EmpImpl">
        <constructor-arg type="java.lang.String" value="James"/>
        <constructor-arg type="int" value="3500"/>
        <constructor-arg type="java.util.Date" ref="hdate"/>
    </bean>
    <bean id="hdate" class="java.util.Date"/>
</beans>
cs

 

[Main Class] HelloSpringEx05.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package ex05;
 
public class HelloSpringEx05 {
 
    public static void main(String[] args) {
        String resource = "classpath:ex05/emp.xml";
        //classpath: class파일이 있는 경로
//(C:\multicampus\Spring-workspace\Spring01_IOC\target\classes)
        
        //스프링 컨테이너
        ApplicationContext ctx = new ClassPathXmlApplicationContext(resource);
        Emp e = ctx.getBean("e2", Emp.class); //형변환
        e.info1();
        System.out.println("-------------------");
        ctx.getBean("e3", Emp.class).info2();
        System.out.println("-------------------");
        ctx.getBean("e4", Emp.class).info3();
        
    }
 
}
cs

실행 결과

 


ex06: xml이 아닌 Java 클래스를 이용해 빈을 생성하고 주입 (Java 기반)

Spring Bean이란?

  • 빈(Bean)이란 스프링 컨테이너에 의해 관리되는 재사용 가능한 소프트웨어 컴포넌트이다.
  • 스프링 컨테이너가 관리하는 자바 객체를 의미하며, 인스턴스화된 객체를 의미한다.

 

Spring Bean 등록 방법

  1. XML에 직접 등록
  2. @Bean 어노테이션 이용
  3. @Component, @Controller, @Service, @Repository 어노테이션 이용

 

빈 스코프(Bean Scope)

빈이 존재할 수 있는 범위 (생존 범위)

Bean Scope 설명
Singleton default. 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프
Prototype 스프링 컨테이너가 프로토타입 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프
웹 관련 스코프 1. request: 웹 요청이 들어오고 나갈 때까지 유지되는 스코프
2. session: 웹 세션이 생성되고 종료될 때까지 유지되는 스코프
3. application: 웹의 서블릿 컨텍스트와 같은 범위로 유지되는 스코프

 

Singleton 스코프

Singleton 스코프의 빈을 조회하면 스프링 컨테이너는 항상 같은 인스턴스의 빈을 반환한다.

 

Prototype 스코프

Prototype 스코프의 빈을 조회하면 스프링 컨테이너는 항상 새로운 인스턴스를 생성해서 반환한다.

 


[Interface] Service.java

1
2
3
4
5
package ex06;
 
public interface Service {
    void info();
}
cs

 

[Class] ServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package ex06;
 
public class ServiceImpl implements Service {
    
    //property
    private Emp emp; //의존성
    
    public void setEmp(Emp emp) {
        this.emp = emp;
    }
    
    @Override
    public void info() {
        System.out.printf("Name: %s\nDept: %s\nSalary: %d\n"
                emp.getName(), emp.getDept(), emp.getSal());
    
    }
 
}
cs

 

[VO] Emp.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
package ex06;
 
public class Emp {
    
    private String name;
    private String dept;
    private int sal;
    
    public Emp() {
        
    }
    public Emp(String name, String dept, int sal) {
        this.name = name;
        this.dept = dept;
        this.sal = sal;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDept() {
        return dept;
    }
    public void setDept(String dept) {
        this.dept = dept;
    }
    public int getSal() {
        return sal;
    }
    public void setSal(int sal) {
        this.sal = sal;
    }
    
}
cs

 

[설정파일] Config.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
package ex06;
 
@Configuration //현재 Config클래스를 환경설정으로 사용하겠다는 의미
public class Config {
    //스프링은 기본적으로 빈(객체)을 단일객체(Singleton)로 생성해서 관리한다.
    //매번 다른 객체를 생성하고 싶다면 @Scope 값을 prototype으로 지정
    @Bean(name="e1"//<bean id="e1" class="ex06.Emp"/>와 동일
    @Scope(value = "singleton")//매번 단일 객체 생성함. 디폴트값은 singleton
    //@Scope(value = "prototype")//매번 다른 객체 생성함. 디폴트값은 singleton
    public Emp empInfo() {
        return new Emp("Ward""Sales"2800);
    }
    //@Bean에 name 속성을 주지 않으면 메서드 이름이 빈의 이름이 된다. (empInfo2)
    @Bean
    public Emp empInfo2() {//<bean id="empInfo2" class="ex06.Emp"/>와 동일
        Emp e = this.empInfo();
        e.setName("Scott");
        e.setDept("Reserach");
        e.setSal(3000);
        return e;
    }
    @Bean
    public ServiceImpl service() {
        ServiceImpl svc = new ServiceImpl();
        svc.setEmp(this.empInfo());
        return svc;
    }
}
cs
  1. @Scope(value = "singleton"): 매번 단일 객체 생성함. 디폴트값
  2. @Scope(value = "prototype"): 매번 다른 객체 생성함
@Configuration + @Bean (수동 방식)
  • Config 클래스에 @Configuration을 적용했다면, 수동으로 각 @Bean 어노테이션을 적용할 메서드들을 작성해야 한다.
  • 수동 방식은 Config 클래스 안에 @Bean을 추가한 메서드로 직접 빈을 등록하며, 의존성 주입도 여기서 진행한다. 이때 @Bean에 name 속성을 주지 않으면 메서드 이름이 빈의 이름이 된다.

 

[Main Class] HelloAppEx06.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package ex06;
 
public class HelloAppEx06 {
 
    public static void main(String[] args) {
        //FileSystemXmlApplicationContext, ClassPathXmlApplicationContext ==> xml설정시
        //AnnotationConfigApplicationContext ==> 자바로 설정시
        ApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
        Emp e1 = ctx.getBean("e1", Emp.class);
        System.out.println(e1.getName() + "/" + e1.getDept() + "/" + e1.getSal());
        
        Emp e2 = ctx.getBean("empInfo2", Emp.class);
        System.out.println(e2.getName() + "/" + e2.getDept() + "/" + e2.getSal());
        System.out.println("***************************");
        
        //service Bean 룩업해서 info()호출
        Service service = ctx.getBean("service", Service.class); //형변환
        service.info();
 
    }
 
}
cs

 

1. @Scope(value = "singleton")인 경우

실행 결과

 

2. @Scope(value = "prototype")인 경우

실행 결과

 


ex07: Java 클래스를 이용해 빈을 생성하되, 인젝션 어노테이션을 이용

의존성 주입 어노테이션

  1. @Value: 기본자료형, String 유형을 주입할 때 사용
  2. @Autowired: byType으로 주입한다. (자료형이 같은 객체를 찾아서 주입)
    • @Qualifier: 동일한 타입의 빈 객체가 여러 개 정의되어 있을 경우 @Qualifier("빈이름")으로 찾는다.
    • 찾는 순서- byType > @Qualifier
  3. @Inject: @Autowired와 마찬가지로 byType으로 주입한다. (자료형이 같은 객체를 찾아서 주입)
    • 과거에는 @Autowired가 많이 쓰였지만, 최근에는 @Inject를 더 많이 쓴다.
    • pom.xml에 라이브러리를 등록해야 사용 가능하다.
  4. @Resource: byName(id)으로 주입한다. pom.xml에 라이브러리를 등록해야 사용 가능하다.

 

[Interface] Service

1
2
3
4
5
6
package ex07;
 
public interface Service {
    void info1();
    void info2();
}
cs

 

[VO] Emp.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
package ex07;
 
public class Emp {
    
    private String name;
    private String dept;
    private int sal;
    
    public Emp() {
        
    }
    public Emp(String name, String dept, int sal) {
        this.name = name;
        this.dept = dept;
        this.sal = sal;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDept() {
        return dept;
    }
    public void setDept(String dept) {
        this.dept = dept;
    }
    public int getSal() {
        return sal;
    }
    public void setSal(int sal) {
        this.sal = sal;
    }
    
}
cs

 

[VO2] Member.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package ex07;
 
public class Member {
    //annotation을 이용하여 값을 주입 => field injection
    @Value("hong"
    private String userId;
    
    @Value("010-1234-1111")
    private String tel;
    
    public void showInfo() {
        System.out.println("UserId: " + userId);
        System.out.println("Tel: " + tel);
    }
}
 
cs

 

[설정파일] AppConfig.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
package ex07;
 
@Configuration
public class AppConfig {
    //Emp빈을 반환하는 메서드 구현 (id=emp1)
    @Bean(name="emp1")
    @Scope("prototype")
    public Emp getEmp() {
        return new Emp("김사원""영업부"7000);
    }
    //Emp빈을 반환하는 메서드 구현 (id=emp2)
    @Bean(name="emp2")
    public Emp getEmp2() {
        Emp e = this.getEmp();
        e.setName("최사원");
        e.setDept("인사부");
        e.setSal(5000);
        return e;
    }
    
    //Member빈을 반환하는 메서드 구현
    @Bean
    public Member member() {
        return new Member();
    }
    
    //ServiceImpl빈을 반환하는 메서드 구현
    @Bean
    public ServiceImpl service() {
        return new ServiceImpl();
    }
}
cs

 

[Class] ServiceImpl.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
package ex07;
 
public class ServiceImpl implements Service {
    
    @Inject
    @Qualifier("emp2")
    private Emp emp;
    
    @Resource(name="member")//빈의 이름이 member인 객체를 찾아서 주입
    private Member user;
    
    @Override
    public void info1() {
        System.out.println("Name: " + emp.getName());
        System.out.println("Dept: " + emp.getDept());
        System.out.println("Salary: " + emp.getSal());
    }
 
    @Override
    public void info2() {
        user.showInfo();        
    }
    
}
cs

 

[Main Class] HelloAppEx07.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package ex07;
 
public class HelloAppEx07 {
 
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        
        Service svc = ctx.getBean("service", Service.class);
        svc.info1();
        System.out.println("************************");
        svc.info2();
 
    }
 
}
cs

실행 결과

 

ServiceImpl에서 emp2 객체를 주입하였으므로 그에 해당하는 최사원의 정보가 출력된다.

1
2
3
@Inject
@Qualifier("emp2")
private Emp emp;
cs

 

+ Recent posts