
스프링이 적용되지 않은 순수한 DI 컨테이너
@Test
@DisplayName("스프링 없는 순수한 DI 컨테이너")
void pureContainer(){
AppConfig appConfig = new AppConfig();
//1. 조회: 호출할 때 마다 객체를 생성
MemberService memberService1 = appConfig.memberService();
//2. 조회: 호출할 때 마다 객체를 생성
MemberService memberService2 = appConfig.memberService();
//참조값이 다른 것을 확인
System.out.println("memberService1 = " + memberService1);
System.out.println("memberService2 = " + memberService2);
// memberService1 = hello.core.member.MemberServiceImpl@24269709
// memberService2 = hello.core.member.MemberServiceImpl@2aceadd4
//memberService1 != memberService2
assertThat(memberService1).isNotSameAs(memberService2);
}
이와 같이, 스프링 빈 컨테이너를 사용하지 않는 DI는 요청할 때마다 새로운 객체를 생성한다.
싱글톤 패턴을 만드는 방법
package hello.core.singleton;
public class SingletonService {
//클래스 내에 미리 객체를 생성해두기
private static final SingletonService instatnce = new SingletonService();
/*
"private static final"은 이 변수를 클래스 내부에서만 접근 가능하며, 값이 변경되지 않음
"SingletonService instance" 변수에 "new SingletonService()"를 할당하여 이 클래스의 유일한 인스턴스를 생성
new SingletonService(); 불가능
*/
//외부에서 객체를 호출할 방법 정의
public static SingletonService getInstance(){
return instatnce;
}
/*
객체를 불러올 수 있는 유일한 방법은 메소드의 리턴값으로 보내는 것이다.
이 메서드를 호출하면 최초에 생성된 인스턴스를 반복적으로 반환한다.
*/
//객체 추가 생성 방지
private SingletonService(){
}
//private 접근제한자로 인해 외부에서 new SingletonService() 로 객체를 생성할 수 없다.
public void logic(){
System.out.println("싱글톤 객체 로직 호출");
}
}
<aside> 💡 "static"은 자바 프로그래밍에서 사용되는 키워드로, 클래스의 공유 멤버를 의미한다. 정적 멤버(static member)는 클래스 이름을 통해 접근할 수 있으며, 클래스의 인스턴스를 생성하지 않고도 사용할 수 있다. 즉, 클래스의 모든 인스턴스가 공유하는 변수와 메서드를 표현할 때 사용할 수 있다.
예를 들어, 클래스에서 static 변수를 선언하면, 클래스의 모든 인스턴스가 같은 값을 가지는 공유 변수가 된다. 메서드에 static 선언 시 클래스의 모든 인스턴스가 공유하는 메서드를 표현할 때 사용할 수 있다.
결론적으로, static은 클래스의 공유 멤버를 의미하며, 클래스의 모든 인스턴스가 공유하는 변수와 메서드를 표현할 때 사용한다.
</aside>
검증하기
@Test
@DisplayName("싱글톤 패턴을 적용한 객체 사용")
void singletonServiceTest(){
SingletonService singletonService1 = SingletonService.getInstance();
//싱글톤 클래스에서 미리 만들어둔 객체를 호출한다.
SingletonService singletonService2 = SingletonService.getInstance();
//한번 더 호출해서 다른 변수에 할당한다.
System.out.println("singletonService1 = " + singletonService1);
System.out.println("singletonService2 = " + singletonService2);
assertThat(singletonService1).isSameAs(singletonService2);
}