SeamFramework.orgCommunity Documentation
생산자 방식은 Web Bean 관리자가 애플리케이션 대신 인스턴스 객체에 응답할 때 발생할 수 있는 특정한 한계를 극복할 수 있게 합니다. Web Beans이 아닌 객체를 Web Beans 환경으로 통합하기 위한 가장 쉬운 방법이 있습니다. (12장. XML을 사용하여 Web Beans 정의 에서 두번째 방법에 대해 살펴보겠습니다.)
spec에 의하면:
Web Beans 생산자 방식은 삽입될 객체 소스로 작동합니다, 여기서
삽입될 객체는 Web Beans의 인스턴스가 될 필요가 없습니다,
삽입되야 할 객체의 구체적 타입은 런타임 시 달라질 수 있습니다
사용자 정의 초기화가 필요한 객체는 Web Bean 생성자에 의해 실행되지 않습니다
예를 들어, 생산자 방식은 다음을 허용합니다:
Web Bean으로서 JPA 엔티티 노출,
Web Bean으로서 JDK 클래스 노출,
동일한 구현 클래스에 대해 다른 범위 또는 초기화를 사용하여 여러 Web Beans를 정의,
런타임 시 다양한 API 유형 구현.
특히, 생산자 방식은 Web Beans를 사용하여 런타임 다형성을 사용하게 합니다. 이미 알고 있듯이, 배치 유형은 배치 시간 다형성 문제의 강력한 해결책입니다. 하지만 일단 시스템이 운용되면 Web Bean 구현은 고정됩니다. 생산자 방식은 이러한 한계를 갖지 않습니다:
@SessionScoped
public class Preferences {
private PaymentStrategyType paymentStrategy;
...
@Produces @Preferred
public PaymentStrategy getPaymentStrategy() {
switch (paymentStrategy) {
case CREDIT_CARD: return new CreditCardPaymentStrategy();
case CHEQUE: return new ChequePaymentStrategy();
case PAYPAL: return new PayPalPaymentStrategy();
default: return null;
}
}
}
삽입 지점 고려:
@Preferred PaymentStrategy paymentStrat;
이러한 삽입 지점은 동일한 유형을 갖으며 생산자 방식으로 어노테이션을 바인딩하므로, 일반적인 Web Beans 삽입 규칙을 사용하여 생산자 방식을 해결합니다. 생산자 방식은 Web Bean 관리자에 의해 호출되어 이러한 삽입 지점을 서비스하기 위해 인스턴스를 획득합니다.
.생산자 방식의 기본값 범위는 @Dependent
로 되어 있으므로, 매 번 Web Bean 관리자가 이러한 영역 또는 동일한 생산자 방식으로 해결되는 다른 영역을 삽입할 때 마다 호출됩니다. 따라서, 각각의 사용자 세션에 대해 PaymentStrategy
객체의 인스턴스가 여러개 있을 수 있습니다.
이러한 기능을 변경하려면, @SessionScoped
어노테이션 방식을 추가할 수 있습니다.
@Produces @Preferred @SessionScoped
public PaymentStrategy getPaymentStrategy() {
...
}
이제 생산자 방식이 호출되면, 반환된 PaymentStrategy
는 세션 컨텍스트로 바운드됩니다. 동일한 세션에서 생산자 방식은 다시 호출되지 않습니다.
위의 코드에 한 가지 문제가 있을 수 있습니다. CreditCardPaymentStrategy
구현은 Java new
연산자를 사용하여 인스턴스화됩니다. 애플리케이션에 의해 직접 인스턴스화된 객체는 의존성 삽입의 장점을 취할 수 없으며 인터셉터를 갖지 못합니다.
이러한 방식을 원하지 않을 경우, 의존성 삽입을 생산자 방식으로 사용하여 Web Bean 인스턴스를 획득할 수 있습니다:
@Produces @Preferred @SessionScoped
public PaymentStrategy getPaymentStrategy(CreditCardPaymentStrategy ccps,
ChequePaymentStrategy cps,
PayPalPaymentStrategy ppps) {
switch (paymentStrategy) {
case CREDIT_CARD: return ccps;
case CHEQUE: return cps;
case PAYPAL: return ppps;
default: return null;
}
}
CreditCardPaymentStrategy
가 요청 범위 Web Bean이면 어떻게 합니까? 이럴 경우 생산자 방식은 현재 요청 범위 임스턴스를 세선 범위로 "활성화되게" 됩니다. 이는 버그입니다! 요청 범위 객체는 세션이 종료되기 전 Web Bean 관리자에 의해 삭제되지만, 객체에 대한 참조는 세션 범위에 "남아 있게" 됩니다. 이러한 오류는 Web Bean 관리자에 의해 검출되지 않으므로 생산자 방식에 Web Bean 인스턴스를 반환할 경우 각별히 주의하시기 바랍니다!
이러한 버그를 해결할 수 있는 세 가지 방법이 있습니다. CreditCardPaymentStrategy
구현 범위를 변경할 수 있지만, Web Bean의 클라이언트에 영향을 미칠 수 있습니다. 보다 나은 방법으로 생산자 방식의 범위를 @Dependent
또는 @RequestScoped
로 변경하는 것입니다.
하지만 보다 일반적인 방법은 특별한 @New
바인딩 어노테이션을 사용하는 것입니다.
다음과 같은 생산자 방식을 고려합니다:
@Produces @Preferred @SessionScoped
public PaymentStrategy getPaymentStrategy(@New CreditCardPaymentStrategy ccps,
@New ChequePaymentStrategy cps,
@New PayPalPaymentStrategy ppps) {
switch (paymentStrategy) {
case CREDIT_CARD: return ccps;
case CHEQUE: return cps;
case PAYPAL: return ppps;
default: return null;
}
}
CreditCardPaymentStrategy
의 새로운 의존성 인스턴스가 생성되면, 생산자 방식으로 전달하고, 생산자 방식에 의해 반환된 후, 마지막으로 세션 컨텍스트로 바운딩됩니다. 의존성 객체는 세션 마지막에 Preferences
객체가 삭제될 때 까지 삭제되지 않습니다.