Loading...
Spring Framework Reference Documentation 7.0.2의 Using TargetSource Implementations의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
TargetSource ImplementationsSpring은 org.springframework.aop.TargetSource 인터페이스에 표현된 TargetSource 개념을 제공합니다. 이 인터페이스는 조인 포인트를 구현하는 “target 객체”를 반환하는 역할을 합니다. TargetSource 구현은 AOP 프록시가 메서드 호출을 처리할 때마다 target 인스턴스를 요청받습니다.
Spring AOP를 사용하는 개발자는 일반적으로 TargetSource 구현과 직접 작업할 필요는 없지만, 이는 풀링, 핫 스와핑 및 기타 정교한 target을 지원하는 강력한 수단을 제공합니다. 예를 들어, 풀링 TargetSource는 풀을 사용하여 인스턴스를 관리함으로써 각 호출마다 다른 target 인스턴스를 반환할 수 있습니다.
TargetSource를 지정하지 않으면, 로컬 객체를 감싸는 기본 구현이 사용됩니다. 동일한 target이 각 호출마다 반환됩니다(예상한 대로입니다).
이 섹션의 나머지 부분에서는 Spring에서 제공하는 표준 target 소스와 이를 사용하는 방법을 설명합니다.
커스텀 target 소스를 사용할 때, target은 일반적으로 싱글톤 빈 정의가 아니라 프로토타입이어야 합니다. 이렇게 하면 필요할 때 Spring이 새로운 target 인스턴스를 생성할 수 있습니다.
org.springframework.aop.target.HotSwappableTargetSource는 호출자가 그에 대한 참조를 유지하면서도 AOP 프록시의 target을 전환할 수 있도록 존재합니다.
target 소스의 target을 변경하면 즉시 적용됩니다. HotSwappableTargetSource는 스레드 세이프합니다.
다음 예제에서 보듯이 HotSwappableTargetSource에서 swap() 메서드를 사용하여 target을 변경할 수 있습니다:
1HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper"); 2Object oldTarget = swapper.swap(newTarget);
1val swapper = beanFactory.getBean("swapper") as HotSwappableTargetSource 2val oldTarget = swapper.swap(newTarget)
다음 예제는 필요한 XML 정의를 보여 줍니다:
1<bean id="initialTarget" class="mycompany.OldTarget"/> 2 3<bean id="swapper" class="org.springframework.aop.target.HotSwappableTargetSource"> 4 <constructor-arg ref="initialTarget"/> 5</bean> 6 7<bean id="swappable" class="org.springframework.aop.framework.ProxyFactoryBean"> 8 <property name="targetSource" ref="swapper"/> 9</bean>
앞선 swap() 호출은 스와퍼블 빈의 target을 변경합니다. 해당 빈에 대한 참조를 보유한 클라이언트는 변경 사실을 알지 못하지만 즉시 새로운 target을 사용하기 시작합니다.
이 예제는 어떠한 어드바이스도 추가하지 않지만(TargetSource를 사용하기 위해 어드바이스를 추가할 필요는 없습니다), 임의의 어드바이스와 함께 어떤 TargetSource든 사용할 수 있습니다.
풀링 target 소스를 사용하면, 동일한 인스턴스의 풀을 유지하고 메서드 호출이 풀의 사용 가능한 객체로 전달되는 상태 비저장 세션 EJB와 유사한 프로그래밍 모델을 제공합니다.
Spring 풀링과 SLSB 풀링의 중요한 차이점은 Spring 풀링이 어떤 POJO에도 적용될 수 있다는 점입니다. 일반적인 Spring과 마찬가지로, 이 서비스는 비침투적인 방식으로 적용될 수 있습니다.
Spring은 상당히 효율적인 풀링 구현을 제공하는 Commons Pool 2를 지원합니다. 이 기능을 사용하려면 애플리케이션의 클래스패스에 commons-pool JAR가 필요합니다. 또한 다른 어떤 풀링 API든 지원하기 위해 org.springframework.aop.target.AbstractPoolingTargetSource를 서브클래싱할 수 있습니다.
다음 리스트는 예제 설정을 보여 줍니다:
1<bean id="businessObjectTarget" class="com.mycompany.MyBusinessObject" 2 scope="prototype"> 3 ... properties omitted 4</bean> 5 6<bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPool2TargetSource"> 7 <property name="targetBeanName" value="businessObjectTarget"/> 8 <property name="maxSize" value="25"/> 9</bean> 10 11<bean id="businessObject" class="org.springframework.aop.framework.ProxyFactoryBean"> 12 <property name="targetSource" ref="poolTargetSource"/> 13 <property name="interceptorNames" value="myInterceptor"/> 14</bean>
target 객체(앞선 예제의 businessObjectTarget)는 프로토타입이어야 합니다. 이렇게 하면 PoolingTargetSource 구현이 필요에 따라 풀을 확장하기 위해 target의 새로운 인스턴스를 생성할 수 있습니다. 그 프로퍼티에 대한 정보는 AbstractPoolingTargetSource의 javadoc과 사용하려는 구체 서브클래스를 참조하십시오.
maxSize는 가장 기본적인 프로퍼티이며 항상 존재함이 보장됩니다.
이 경우, myInterceptor는 동일한 IoC 컨텍스트에서 정의되어야 하는 인터셉터의 이름입니다. 그러나 풀링을 사용하기 위해 인터셉터를 지정할 필요는 없습니다. 풀링만 사용하고 다른 어드바이스는 사용하지 않으려면, interceptorNames 프로퍼티를 전혀 설정하지 마십시오.
Spring을 구성하여, 인트로덕션을 통해 풀의 설정 및 현재 크기에 대한 정보를 노출하는 org.springframework.aop.target.PoolingConfig 인터페이스로 모든 풀링된 객체를 캐스트할 수 있게 할 수 있습니다. 다음과 유사한 어드바이저를 정의해야 합니다:
1<bean id="poolConfigAdvisor" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> 2 <property name="targetObject" ref="poolTargetSource"/> 3 <property name="targetMethod" value="getPoolingConfigMixin"/> 4</bean>
이 어드바이저는 AbstractPoolingTargetSource 클래스의 편의 메서드를 호출하여 얻기 때문에 MethodInvokingFactoryBean을 사용합니다. 이 어드바이저의 이름(여기서는 poolConfigAdvisor)은 풀링된 객체를 노출하는 ProxyFactoryBean의 인터셉터 이름 목록에 포함되어야 합니다.
캐스트는 다음과 같이 정의됩니다:
1PoolingConfig conf = (PoolingConfig) beanFactory.getBean("businessObject"); 2System.out.println("Max pool size is " + conf.getMaxSize());
1val conf = beanFactory.getBean("businessObject") as PoolingConfig 2println("Max pool size is " + conf.maxSize)
상태 비저장 서비스 객체를 풀링하는 것은 보통 필요하지 않습니다. 대부분의 상태 비저장 객체는 본질적으로 스레드 세이프이며, 인스턴스 풀링은 리소스가 캐시되는 경우 문제가 될 수 있기 때문에, 우리는 이것이 기본 선택이 되어야 한다고 믿지 않습니다.
더 간단한 풀링은 오토 프록시를 사용하여 사용할 수 있습니다. 모든 오토 프록시 생성기에서 사용되는 TargetSource 구현을 설정할 수 있습니다.
“prototype” target 소스를 설정하는 것은 풀링 TargetSource를 설정하는 것과 유사합니다. 이 경우, 각 메서드 호출마다 target의 새로운 인스턴스가 생성됩니다.
모던 JVM에서 새로운 객체를 생성하는 비용은 크지 않지만, 새로운 객체를 와이어링(IoC 의존성을 충족시키는 것)하는 비용은 더 비쌀 수 있습니다. 따라서 매우 타당한 이유가 없다면 이 접근 방식을 사용해서는 안 됩니다.
이를 위해, 앞에서 보여 준 poolTargetSource 정의를 다음과 같이 수정할 수 있습니다(명확성을 위해 이름도 변경했습니다):
1<bean id="prototypeTargetSource" class="org.springframework.aop.target.PrototypeTargetSource"> 2 <property name="targetBeanName" ref="businessObjectTarget"/> 3</bean>
유일한 프로퍼티는 target 빈의 이름입니다. 일관된 네이밍을 보장하기 위해 TargetSource 구현에서 상속이 사용됩니다. 풀링 target 소스와 마찬가지로, target 빈은 프로토타입 빈 정의이어야 합니다.
ThreadLocal Target SourcesThreadLocal target 소스는 각 인커밍 요청(즉, 스레드당 하나)에 대해 객체를 생성해야 할 때 유용합니다. ThreadLocal 개념은 스레드와 함께 리소스를 투명하게 저장하기 위한 JDK 전역 기능을 제공합니다.
다음 예제에서 보듯이, ThreadLocalTargetSource를 설정하는 것은 다른 유형의 target 소스에 대해 설명한 것과 거의 동일합니다:
1<bean id="threadlocalTargetSource" class="org.springframework.aop.target.ThreadLocalTargetSource"> 2 <property name="targetBeanName" value="businessObjectTarget"/> 3</bean>
ThreadLocal인스턴스는 멀티스레드 및 멀티 클래스 로더 환경에서 잘못 사용할 경우(잠재적으로 메모리 누수를 초래하는) 심각한 문제를 유발합니다. 항상ThreadLocal을 다른 클래스로 감싸고, (래퍼 클래스를 제외하고는)ThreadLocal자체를 직접 사용하지 않도록 해야 합니다. 또한 스레드에 로컬한 리소스를 올바르게 설정 및 해제(후자는ThreadLocal.remove()호출을 포함)해야 함을 항상 기억해야 합니다. 해제는 어떤 경우에도 수행해야 하며, 해제하지 않으면 문제가 되는 동작을 초래할 수 있습니다. Spring의ThreadLocal지원은 이를 대신 처리해 주며, 다른 적절한 처리 코드 없이ThreadLocal인스턴스를 사용하는 것보다 항상 우선적으로 고려해야 합니다.
Using the "auto-proxy" facility
Defining New Advice Types