본문 바로가기
프로그래밍

Spring Scoped Proxy Beans (prototype 빈 DI로 주입해서 사용)

by 탁구치는 개발자 2016. 1. 14.

Spring 에서의 IoC 방식은 두 가지가 있다.


DI, DL 방식

DI 방식은 주입되는 객체의 인스턴스가 싱글톤일 때 사용하고,

DL 방식은 매번 새로운 인스턴스를 생성하여 빈을 사용하고자 할 때 이용되는 것으로만 알고 있었다.


허나, 팀 동료로부터 새로운 정보를 들었는데

DI 방식으로 의존성 주입된 빈을 사용할 때마다 새로운 인스턴스의 빈으로 연결 받을 수 있다고 하였다.


새로운 사실에 놀라 자료를 찾아보고 테스트를 해보니 정말로 가능하다는 것을 알게 되었다.


MemberService는 prototype이 선언된 빈이다.

테스트 클래스에 MemberService를 DI 받고 getMember() 메소드를 10번 호출해 보면 단 한 번의 인스턴스만 생성된 것을 확인할 수 있다.

@Component

@Scope(value = "prototype")

public class MemberService {

 

        public MemberService() {

               System.out.println("New Instance MemberService!!");

        }

 

        public List<String> getList() {

               List<String> memberList = new ArrayList<String>();

               memberList.add("사람1");

               memberList.add("사람2");

               memberList.add("사람3");

               return memberList;

        }

}



@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = {"/spring.xml"})

public class MemberControllerTest {

        @Autowired

        private MemberService memberService;        

 

        @Test

        public void test1() {

               for (int i = 0; i < 10; i++) {

                       memberService.getList();

               }

        }

}







허나, MemberServiceProxy를 DI 받고 getMember() 메서드를 10번 호출해 보면 10번의 인스턴스가 생성된 것을 확인할 수 있다.

@Component

@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS, value = "prototype")

public class MemberServiceProxy {

 

        public MemberServiceProxy() {

               System.out.println("New Instance MemberServiceProxy!!");

        }

 

        public List<String> getList() {

               List<String> memberList = new ArrayList<String>();

               memberList.add("사람1");

               memberList.add("사람2");

               memberList.add("사람3");

               return memberList;

        }

}


@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = {"/spring.xml"})

public class MemberControllerTest {

        @Autowired

        private MemberServiceProxy memberServiceProxy;


        @Test

        public void test2() {

               for (int i = 0; i < 10; i++) {

                       memberServiceProxy.getList();

               }

        }

}




이는 scoped proxy로 빈을 등록해 주면 프록시 오브젝트가 싱글톤 빈에서 prototype 빈으로의 메소드 호출을 가로채 새로 생성된 prototype 빈으로 연결해 주기 때문이다.


참고로 scoped proxy를 사용하기 위해서는 cglib 라이브러리가 필요하다.