2012-02-24 4 views
7

나는 병렬 작업을 수행하기 위해 런타임에 몇 가지 작업 (java.util.concurrent.Callable의 것)을 생성하는 싱글 톤 스프링 빈을 얻었다. 지금은 Callable을 싱글 톤 빈의 내부 클래스로 정의하고 싱글 톤 빈은 new Task(in)으로 인스턴스화하여 간단히 만듭니다. 여기서 in은 런타임에만 알려진 매개 변수입니다.Spring : 런타임 매개 변수를 사용하는 Spring 빈을 인스턴스화하는 방법은 무엇입니까?

이제 Task의 call() 메서드를 트랜잭션으로 만들고 싶기 때문에 내부 Task 클래스를 일반 최상위 클래스로 추출하려고합니다. 그래서 Spring 빈이어야합니다.

내 싱글 톤에 Task의 팩토리를 주어야 겠지만, 작업은 생성자 매개 변수로 런타임 값을 사용하는 프로토 타입 스프링 빈이어야합니다. 이것을 어떻게 할 수 있습니까?

+0

@BorisTreukhov : 이것은 멀티 스레드 응용 프로그램 테스트에 대한 질문이 아닙니다. 이것은 Spring에 관한 질문입니다. 실제로, 나는 진짜 문제에서 산만하기 때문에 나의 질문에서 이유 # 2를 제거 할 것이다. –

+0

참조 : http://stackoverflow.com/questions/8772585/spring-bean-with-dynamic-constructor-value – quaylar

+0

@Bossie 내 코멘트를 제거 확인, BTW 나는 간단한 방법은 별도의 서비스를 만드는 것입니다 생각 beans를 사용하여 메소드를 트랜잭션으로 꾸며서 싱글 톤에 삽입하고 "in"매개 변수를 서비스 메소드에 전달합니다. –

답변

2

스프링의 bean 팩토리와 new는 상호 배타적입니다. new를 호출 할 수없고 그 객체가 Spring의 제어를받을 것으로 기대할 수 없습니다.

내 제안은 이러한 작업을 싱글 톤에 주입하는 것입니다. 그들에게 봄 콩도 만들어라.

작업 자체는 트랜잭션이 아니지만 종속성이 될 수 있습니다. 태스크에 이들을 주입하고 Spring이 트랜잭션을 관리하게하십시오.

+0

+1 키스입니다. 필요 이상의 것들을 만들 필요가 없습니다. 트랜잭션 서비스를 만들고이를 태스크에 주입하십시오. – pap

+0

"Spring의 bean factory와 new는 상호 배타적입니다." 대부분의 사람들에게는 분명한 것처럼 보일 수 있지만 봄날 초보자의 경우 이것은 듣기에 매우 중요했습니다. 봄이 실제로 무엇을하는지 이해할 수있었습니다. –

+0

하지만 작업 수를 모르는 경우 어떻게해야합니까? 나는. 누군가가 숫자 10으로 작업을 제출하고 10 개의 작업을 인스턴스화합니까? 이런 경우 Tasks를 Singleton에 주입하는 방법을 알려주십시오. –

3

싱글 톤 bean은 포함 봄 팩토리에서 BeanFactoryAware 및 lookup beans를 구현할 수 있습니다.

import org.springframework.beans.BeansException; 
import org.springframework.beans.factory.BeanFactory; 
import org.springframework.beans.factory.BeanFactoryAware; 

public class MyBeanFactory implements BeanFactoryAware { 

    private BeanFactory beanFactory; 

    public void setBeanFactory(BeanFactory beanFactory) 
      throws BeansException { 
     this.beanFactory = beanFactory;  
    } 

    public Task createTask(Task in) { 
     return beanFactory.getBean("task",in); 
    } 

} 
/////////////// 

import java.util.concurrent.Callable; 
import org.springframework.beans.factory.annotation.Configurable; 
import org.springframework.context.annotation.Scope; 
import org.springframework.transaction.annotation.Transactional; 

@Configurable // unless using xml based config 
@Scope(value="prototype") // tell bean factory to create new instance each time 
public class Task implements Callable<Object> { 

    private Object in; 

    public Task(Object in) { 
     super(); 
     this.in = in; 
    } 

    @Transactional 
    public Object call() throws Exception { 
     //do real work 
     return in; 
    } 
} 
/// 
4

또 다른 방법은로드 시간 직물과 봄의 @Configurable 주석을 사용할 수 있습니다, 당신은 런타임에 유선 호출 가능의를 만들 (대신 콩 공장) new를 사용할 수있는이 방법 :

@Configurable 
public class WiredTask implements Callable<Result> { 

    @Autowired 
    private TaskExecutor executor; 

    public WiredTask(String in) { 
     this.in = in; 
    } 

    public Result call() { 
     return executor.run(in); 
    } 
} 

@Bean @Scope("prototype") 
public class TaskExecutor() { 

    @Transactional 
    public Result run(String in) { 
     ... 
    } 
} 

// Example of how you might then use it in your singleton... 
ExecutorService pool = Executors.newFixedThreadPool(3); 
WiredTask task = new WiredTask("payload"); 
Future<Result> result = pool.submit(task); 

참조 자세한 내용은 this article을 참조하십시오. 참고로 @Configurable and @Transactional in the same bean을 사용할 수 없으므로 두 클래스가 필요합니다. 이러한 이유 때문에 Callable의 구현이 다양 할 경우 (각 클래스마다 2 개의 클래스가 필요하기 때문에) 이상적인 솔루션이 아닐 수도 있습니다.

관련 문제