6.9 TargetSource구현체 사용하기 by sh

6.9. TargetSource구현체 사용하기

Spring은 org.springframework.aop.TargetSource인터페이스에 표현 된 TargetSource의 개념을 제공합니다. 이 인터페이스는 조인 포인트를 구현하는 "대상 객체"를 반환합니다. TargetSource구현은 AOP 프록시가 메소드 호출을 처리 할 때마다 대상 인스턴스를 요청받습니다.

Spring AOP를 사용하는 개발자는 일반적으로 TargetSource구현체로 직접 작업 할 필요가 없지만 풀링, 핫 스왑 및 기타 정교한 타겟을 지원하는 강력한 수단을 제공합니다. 예를 들어 Pooling TargetSource는 인스턴스를 관리하기 위해 풀을 사용하여 각 호출에 대해 다른 대상 인스턴스를 반환 할 수 있습니다.

TargetSource를 지정하지 않으면 기본 구현을 사용하여 로컬 객체를 래핑합니다. 각 호출에 대해 동일한 대상이 반환됩니다 (예상대로).

이 절의 나머지 부분에서는 Spring에서 제공되는 표준 대상 소스와 그 사용 방법에 대해 설명합니다.

스프링 AOP의 TargetSource 개념 : AOP의 동작 과정에서 대상 객체를 가져오는 부분에 들어가는 조인포인트. (AOP를 적용한 최종 객체를 가져오는 과정에 개입한다는 의미)

-> TargetSource의 활용 : Hot Swappable TargetSource, Pooling TargetSource
    -> Pooling TargetSource 전략 3가지 : 
        1. 매번 새 대상 객체를 돌려주는 prototypeTargetSource
        2. 같은 쓰레드에서는 같은 객체를 반복적으로 돌려주는 ThreadLocalTargetSource
        3. commons.pool을 이용한 객체 풀링을 지원하는 CommonsPoolTargetSource 

사용자 정의 대상 소스를 사용할 때 대상은 일반적으로 단일 bean 정의가 아닌 프로토 타입이어야합니다. 이렇게하면 Spring이 필요할 때 새로운 타겟 인스턴스를 생성 할 수있습니다.

6.9.1. Hot-swappable Target Sources

org.springframework.aop.target.HotSwappableTargetSource는 호출자가 AOP 프록시의 대상에 대한 참조를 유지하는 동안 AOP 프록시 대상을 교체 할 수 있도록하기 위해 존재합니다.

argetSource의 대상 변경은 즉시 적용됩니다. HotSwappableTargetSource는 스레드로부터 안전합니다.

즉, 런 타임에 대상을 바꾸고 변경하려는 빈의 프록시를 사용하는 것. AOP 지원 클래스.

(HotSwappableTargetSource를 사용하면 쉽게 할 수 있음)

다음 예제와 같이 HotSwappableTargetSource에서 swap() 메서드를 사용하여 대상을 변경할 수 있습니다.

HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper");
Object oldTarget = swapper.swap(newTarget);

다음 예제에서는 필수 XML 정의를 보여줍니다.

<bean id="initialTarget" class="mycompany.OldTarget"/>

<bean id="swapper" class="org.springframework.aop.target.HotSwappableTargetSource">
    <constructor-arg ref="initialTarget"/>
</bean>

<bean id="swappable" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="targetSource" ref="swapper"/>
</bean>

앞의 swap() 호출은 스왑 가능한 빈의 대상을 변경합니다. 해당 bean에 대한 참조를 보유한 클라이언트는 변경을 인식하지 않지만 즉시 새 대상을 시작합니다.

이 예는 어떤 advice도 추가하지 않았지만 (TargetSource를 사용하기 위해 advice를 추가 할 필요는 없습니다) 임의의 advice와 결합해서 모든 TargetSource를 사용할 수 있습니다.

6.9.2. Pooling Target Sources

TargetSource의 풀링을 사용하면, 상태가 없는 세션 EJB와 유사한 프로그래밍 모델을 제공합니다. 이 프로그래밍 모델은 동일한 인스턴스 풀을 유지하고 메서드 호출로 풀에서 객체를 가져옵니다.

스프링 풀링과 SLSB 풀링의 중요한 차이점은 스프링 풀링은 모든 POJO에 적용 할 수 있다는 것입니다. 일반적으로 Spring과 마찬가지로,이 서비스는 비 침습적 인 방식으로 적용될 수 있습니다.

스프링은 상당히 효율적인 풀링 구현을 제공하는 Commons Pool 2.2를 지원합니다. 이 기능을 사용하려면 응용 프로그램의 classpath에 commons-poolJar가 필요합니다. 다른 풀링 API를 지원하기 위해 org.springframework.aop.target.AbstractPoolingTargetSource의 서브 클래스 화를 수행 할 수도 있습니다.

Commons Pool 1.5+도 지원되지만 Spring Framework 4.2에서는 더 이상 사용되지 않습니다.

다음 목록은 구성 예제를 보여줍니다.

<bean id="businessObjectTarget" class="com.mycompany.MyBusinessObject"
        scope="prototype">
    ... properties omitted
</bean>

<bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPool2TargetSource">
    <property name="targetBeanName" value="businessObjectTarget"/>
    <property name="maxSize" value="25"/>
</bean>

<bean id="businessObject" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="targetSource" ref="poolTargetSource"/>
    <property name="interceptorNames" value="myInterceptor"/>
</bean>

앞의 예제에서 targetObject (프로토 타입)는 대상 객체 여야합니다. 이를 통해 PoolingTargetSource구현은 대상의 새 인스턴스를 만들어 필요에 따라 풀을 확장 할 수 있습니다. javadoc ofAbstractPoolingTargetSource과 그 속성에 대한 정보를 위해 사용하고자 하는 구체적인 서브 클래스를 보십시오. maxSize가 가장 기본적인 프로퍼티이고 항상 존재한다는 보장이 있습니다.

이 경우 myInterceptor는 동일한 IoC 컨텍스트에서 정의해야하는 인터셉터의 이름입니다. 그러나 풀링을 사용하려면 인터셉터를 지정할 필요는 없습니다. 풀링 만하고 다른 advice는 필요하지 않으면 interceptorNames속성을 전혀 설정하지 마십시오.

풀링 된 객체를 org.springframework.aop.target.PoolingConfig 인터페이스로 형변환 할 수 있도록 Spring을 설정할 수 있습니다. 이 인터페이스는 인트로덕션을 통해 풀의 구성 및 현재 크기에 대한 정보가 노출됩니다. 다음과 유사한 advisor를 정의해야합니다.

<bean id="poolConfigAdvisor" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject" ref="poolTargetSource"/>
    <property name="targetMethod" value="getPoolingConfigMixin"/>
</bean>

이 advisor는 AbstractPoolingTargetSource클래스에서 편리한 메소드를 호출하여 얻어 지므로 MethodInvokingFactoryBean을 사용합니다. 이 advisor의 이름 (poolConfigAdvisor)은 풀링 된 오브젝트를 공개하는 ProxyFactoryBean의 인터셉터 이름 목록에 있어야합니다.

캐스트는 다음과 같이 정의됩니다.

PoolingConfig conf = (PoolingConfig) beanFactory.getBean("businessObject");
System.out.println("Max pool size is " + conf.getMaxSize());

일반적으로 상태 비 저장 서비스 객체를 풀링하는 것은 필요하지 않습니다. 대부분의 상태 비 저장 객체는 자연스럽게 스레드 안전성을 가지기 때문에 기본적인 선택이어야 한다고 생각하지 않고, 리소스가 캐싱되는 경우 인스턴스 풀링이 문제가될 수 있습니다.

자동 프록시를 사용하면보다 간단한 풀링을 사용할 수 있습니다. 자동 프록시 작성자가 사용하는 TargetSource구현을 설정할 수 있습니다.

6.9.3. Prototype Target Sources

"프로토 타입" TargetSource 설정은 풀링 TargetSource설정과 유사합니다. 이 경우 모든 메소드 호출시 목표의 새 인스턴스가 작성됩니다. 현대의 JVM에서는 새로운 객체를 만드는 데 드는 비용이 높지 않지만 새로운 객체를 연결하는 비용 (IoC 의존성 충족)은 더 비쌉니다. 따라서 아주 좋은 이유없이 이 접근법을 사용하지 않아야합니다..

이렇게 하려면 앞에서 설명한 poolTargetSource정의를 다음과 같이 수정할 수 있습니다 (명확하게하기 위해 이름을 변경했습니다).

<bean id="prototypeTargetSource" class="org.springframework.aop.target.PrototypeTargetSource">
    <property name="targetBeanName" ref="businessObjectTarget"/>
</bean>

유일한 특성은 대상 bean의 이름입니다. (대상 빈의 이름을 위한 하나의 프로퍼티만 존재) 상속은 일관된 명명을 보장하기 위해 TargetSource구현에서 사용됩니다. 풀링 대상 소스와 마찬가지로 대상 bean은 프로토 타입 bean 정의 여야합니다.

6.9.4. ThreadLocal Target Sources

ThreadLocalTargetSource는 들어오는 각 요청 (스레드 당)에 대해 객체를 만들어야하는 경우에 유용합니다. ThreadLocal의 개념은 스레드와 나란히 리소스를 투명하게 저장하는 JDK 전역 기능을 제공합니다. ThreadLocalTargetSource를 설정하는 것은 다음 예제와 같이 다른 유형의 대상 소스에 대해 설명 된 것과 거의 같습니다.

<bean id="threadlocalTargetSource" class="org.springframework.aop.target.ThreadLocalTargetSource">
    <property name="targetBeanName" value="businessObjectTarget"/>
</bean>

ThreadLocal 인스턴스는 다중 스레드 및 다중 클래스 로더 환경에서 잘못 사용하면 심각한 문제 (메모리 누수가 발생할 수 있음)가 발생합니다. 다른 클래스에서는 threadlocal을 래핑하는 것을 항상 고려해야하며 ThreadLocal 자체를 직접 사용하지 않아야합니다 (래퍼 클래스 제외). 또한 스레드의 로컬 리소스를 올바르게 설정하고 해제하는 것을 잊지 말아야합니다 (후자는 간단히 ThreadLocal.set (null)에 대한 호출과 관련됩니다). 설정을 해제하지 않으면 문제가 발생할 수 있으므로 설정 해제는 어떤 경우에도 수행해야합니다. Spring의 ThreadLocal 지원은 당신을 위해 이것을 수행하며, 다른 적절한 처리 코드없이 ThreadLocal 인스턴스를 사용하는 것을 항상 고려해야한다.

Last updated