OCP 개발-폐쇄 원칙 => 특정 역할에 의존하고 구현체를 갈아끼우는 식으로 사용자의 기존 코드는 유지한 채 다른 기능으로 확장이 가능
그러나 일반적으로 사용자의 기존 코드에서 변경할 구현체로 변경하지 않고는 구현체 갈아끼우기가 불가능
이를 해결하기 위해서는 외부에서 구현체의 변경을 관리해줘야 한다.
DIP -> 구현체가 아닌 추상화에 의존하는 원칙 => 인터페이스 타입의 변수에 구현체 객체를 할당하는 방법도 이를 위반한 것
MemberRepository repo = new MemoryMemberRepository(); // DIP 위반
스프링 빈은 실제로 런타임에 사용이 필요한 순간에 생성되도록 LazyInit 으로 설정되어 있다.
스프링 컨테이너는 java 코드나 XML 이던 상관 없이 BeanDefinition (빈의 메타정보) 만 알면 된다. 즉, BeanDefinition 을 통해서 빈의 생성 및 연결을 관리할 수 있는 것
싱글톤 객체는 아래와 같은 문제를 가지고 있다.
하지만, 스프링 컨테이너는 위의 문제를 해결해준다.
그래도 싱글톤 객체는 이러한 문제가 있다.
그래서 싱글톤 객체는 Stateless 해야하는 것이 중요
빈을 중복 등록하면 에러 발생 -> BeanDefinitionStoreException
조회한 빈 모두를 사용해야 할 때 Map 또는 List 를 사용할 수 있다.
예를 들어,
interface Policy 가 있고 이를 구현하는 FirstPolicy, SecondPolicy 가 있다면
Map<String, Policy> policyMap / List< Policy> policies 를 활용해 빈을 조회하면
자바 컬렉션 안에 관련된 모든 빈이 나온다
왜냐하면, 스프링은 기본적으로 빈 조회 시 자식에 해당하는 모든 빈이 조회되게 설정되어 있기 때문에 가능
스프링 빈 기본 라이프사이클
빈 스코프
주의해야 할 점!!
싱글톤 빈에서 프로토타입 빈을 사용하는 경우,
프로토타입은 주입 후 초기화까지만 컨테이너에서 관리하기 때문에
프로토타입 빈을 주입받은 싱글톤 빈에서는 이 프로토타입 빈을 계속 사용한다.
즉, 싱글톤 빈에서 프로토타입 빈의 메소드를 호출하는 경우에 계속 같은 빈을 참조함을 의미
이러한 경우에 처음에 의도한 프로토타입 빈을 제대로 활용하지 못하게 된다
이를 해결하려면 프로토타입 빈은 필요할 때마다 새롭게 주입시켜주면 된다.
즉, getBean() 을 필요할 때마다 계속 호출해서 주입시켜주면 됨
이러한 방식을 Dependency Lookup(Dl)/조회(탐색) 의존 관계라고 불리움
하지만, 이렇게 되면 객체가 스프링 컨테이너에 의존하게 되는 문제가 발생한다.
그래서 스프링에서는 ObjectProvider<> 를 제공한다
그러면 싱글톤 스프링 빈에서는 아래와 같이 Provider 를 사용해서 DL 해주면 된다
private ObjectProvider<PrototypeBean> prototypeBeanProvider;
public void temp(){
PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
// TO-DO
}
또는 자바 표준 중 하나인 JSR303 Provider 를 사용할 수도 있다.
웹 스코프 소개
여기서 문제가 발생,
1. HTTP 요청이 안 들어오면 빈 생성 X -> 다른 빈들에서 직접 의존 불가 -> Provider 가 필요
2. 스코프에 proxy 를 추가 -> 가짜 프록시 객체 주입 -> HTTP 요청이 오면 실제 객체에 위임
이 둘이 가지는 장점은 편리하게 의존성을 주입할 수 있음과 동시에 지연처리가 가능하다는 것