티스토리 뷰

Bean객체의 Scope 속성

 


 

 

그동안은 의존성 주입(DI)의 개념에 대해 살펴보았고, 이를 통해 제어의 역전(IoC)이라는 것이 무엇인지에 관해 살펴보았습니다.
그렇다면 이번 시간에는 값을 입력하는 것도 외로도 많은 기능을 살펴보도록 하겠습니다.

학교에 학생이 있습니다.
그동안 스프링에서 의존성 주입을 통해서는 싱글톤 객체로 관리한다는 것까지는 알았는데, 갑자기 학교에서는 이제 학생 여러 명을 관리하고 싶어졌습니다.
그렇다면 어떻게 해야 할까요?

학생.java

public class Student {
    private Pencil pencil;

    public Pencil getPencil() {
        return pencil;
    }

    public void setPencil(Pencil pencil) {
        this.pencil = pencil;
    }

    public void doStudy(String subject) {
        System.out.println(subject + "을 공부하다.");
    }

    @Override
    public String toString() {
        return super.toString() + "번 학생";
    }

}

학생의 toString() 메서드를 오버라이딩하여 객체의 해시코드를 통해 같은 객체가 불렸는지 식별해보도록 하겠습니다.

학교.java

public class School {
    public static void main(String[] args) {
        AbstractApplicationContext context = new GenericXmlApplicationContext("classpath:com/di/school5/xml/scope/applicationContext.xml");

        try {
            System.out.println("스코프");
            Student student = (Student)context.getBean("student"); //DI컨테이너에서 생성된 학생객체 가져오기
            System.out.println(student);
            System.out.println(context.getBean("student",Student.class));
            System.out.println(context.getBean("student",Student.class));
            System.out.println(context.getBean("student",Student.class));
            System.out.println(context.getBean("student",Student.class));
            System.out.println(context.getBean("student",Student.class));
            System.out.println(context.getBean("student",Student.class));
            System.out.println(context.getBean("student",Student.class));
        } finally {
            context.close(); //자원 닫기
        }
    }
}

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">

    <bean id="pencil" class="com.di.school5.xml.scope.Pencil">
        <property name="name" value="몬아미샤프2020"/>
        <property name="length" value="30"/>
        <property name="boldLevel" value="4"/>
        <property name="available" value="true"/>
    </bean>

    <bean id="student" class="com.di.school5.xml.scope.Student" >
        <property name="pencil" ref="pencil"/>
    </bean>

</beans>

이 프로그램을 실행하면 다음과 같은 실행 결과를 나타낼 것입니다.

어찌 보면 당연한 결과가 아니었을까요?
applicationContext.xml에서 bean태그 중 Student클래스의 객체는 id가 student인 bean 객체뿐이 없습니다.
그리고 기본적으로 스프링은 싱글톤으로 관리한다고 했습니다. 그러니까 위의 결과화면에서 똑같은 객체가 계속 호출되는 것은 이상한 현상이 아니죠.

그렇지만, 객체를 참조할 때마다 매번 다른 객체를 꺼내다 쓰고 싶은 경우가 생기지 않을까요?
바로 그러한 상태를 관리하기 위해서 Scope이라는 용어가 등장합니다.
Scope를 prototype속성으로 지정하면 아래와 같이 객체를 참조할 때마다 매번 다른 객체, 즉 다른 학생들이 등장하는 것을 확인하실 수 있습니다.

applicationContext.xml 에서 id가 student인 객체의 속성을 다음과 같이 추가합니다.

<bean id="student" class="com.di.school5.xml.scope.Student" scope="prototype">
    <property name="pencil" ref="pencil"/>
</bean>

그리고 프로그램을 실행해 봅니다.

이제는 객체를 참조할 때마다, 즉 getBean메서드를 호출하면서 Student클래스의 객체를 가져올 떄마다 매번 다른 객체를 꺼내 쓰고 있음을 확인할 수 있습니다.

======

여기까지는 getBean메서드를 이용하여 객체를 참조할 때마다였다면, 이번에는 객체의 메서드를 호출할 때마다 다른 객체를 꺼내서 써볼까요?
그게 무슨 말이냐고요?

학생.java의 클래스를 잠깐 수정해 보겠습니다.

학생.java

public class Student {
    private Pencil pencil;

    public Pencil getPencil() {
        return pencil;
    }

    public void setPencil(Pencil pencil) {
        this.pencil = pencil;
    }

    public void doStudy(String subject) {
        System.out.println(toString() + "이 " + subject + "을 공부하다.");//해시코드 출력
    }

    @Override
    public String toString() {
        return super.toString() + "번 학생";
    }

}

학교.java

public class School {
    public static void main(String[] args) {
        AbstractApplicationContext context = new GenericXmlApplicationContext("classpath:com/di/school5/xml/scope/applicationContext.xml");

        try {
            System.out.println("스코프");
            Student student = (Student)context.getBean("student"); //DI컨테이너에서 생성된 학생객체 가져오기
            student.doStudy("스프링");
            student.doStudy("스프링");
            student.doStudy("스프링");
            student.doStudy("스프링");
            student.doStudy("스프링");
            student.doStudy("스프링");
            student.doStudy("스프링");
            student.doStudy("스프링");
        } finally {
            context.close(); //자원 닫기
        }
    }
}

applicationContext.xml에 다음의 속성 aop:scoped-proxy을 bean태그 하위에 추가합니다.

<bean id="student" class="com.di.school5.xml.scope.Student" scope="prototype">
    <property name="pencil" ref="pencil"/>
    <aop:scoped-proxy/>
</bean>

분명히 객체를 한 번만 참조(getBean)했을 뿐인데 메서드를 호출할 때마다 다른 객체가 메서드 구문을 수행하고 있는 것을 확인할 수 있습니다.

어떠신가요?
기본적으로 scope를 singleton으로 관리한다는 것도 다시 한 번 상기시켰을 뿐만 아니라 이젠 prototype속성을 이용하여 참조할 떄마다 새로운 객체를 불러낼 수 있다는 것도 알 수 있었습니다.
심지어, 객체를 한 번만 참조하였는데도 메서드를 수행할 떄마다 새로운 객체가 메서드를 실행하고 있다는 것도 살펴보았습니다.

 

digest1.zip
0.04MB

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
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
글 보관함