2011-12-07 12 views
7
private final ExecutorService executorParsers = Executors.newFixedThreadPool(10); 

public void parse(List<MyObjInt> objs) { 
    //... bunch of elided stuff .... 

    CompletionService<AsupParseObj> parserService = new ExecutorCompletionService<AsupParseObj>(executorParsers); 

    for (final AsupStoreObj obj : objs) { 
     parserService.submit(new ParseThread(obj)); 
    } 
} 

me gustaría DI el "ParseThread" pero seguro que tiene que haber una mejor manera de hacerlo que enterrar una llamada a getBean en un prototipo con ámbito de frijol y como soy nuevo en la primavera que pensé que le pregunte. ..¿La mejor manera de refactorizar esto en primavera?

+0

Con Spring DI, necesita hacer que su objeto se parezca más a un POJO. Entonces, dado que hay algunas maneras en que puedo imaginar a dónde puede ir con su código. ¿Puedes proporcionar un fragmento más grande y un contexto adicional para lo que intentas hacer? –

+1

parece que su ParseThread no tiene otra dependencia que no sea AsupStoreObject ... en este caso ... ¿qué desea que la primavera ayude? – Dapeng

+1

Bueno, mi intención era poder inyectar los callables ParseThread de modo que pueda cambiar más fácilmente hacia fuera/burlan de aquellos en vez de estar atado ya que este código es una implementación específica del ParseThread – user1085751

Respuesta

7

Aquí es la configuración completa usando lookup-method (ver 3.4.6.1 Lookup method injection):

<bean id="executorParsers" class="java.util.concurrent.Executors" 
     factory-method="newFixedThreadPool" 
     destroy-method="shutdownNow"> 
    <constructor-arg value="10"/> 
</bean> 

<bean id="parserService" class="java.util.concurrent.CompletionService"> 
    <constructor-arg ref="executorParsers"/> 
</bean> 

<bean id="foo" class="Foo"> 
    <lookup-method name="createThread" bean="parseThread"/> 
</bean> 

<bean id="parseThread" class="ParseThread" scope="prototype" lazy-init="true"/> 

Y el código de Java:

abstract class Foo { 

    @Autowired 
    CompletionService parserService; 

    protected abstract ParseThread createThread(); 

    public void parse(List<MyObjInt> objs) { 
     for (final AsupStoreObj obj : objs) { 
      ParseThread t = createThread(); 
      t.setObject(obj); 
      parserService.submit(t); 
     } 
    } 
} 

Desafortunadamente no puede pasar ningún parámetro a lookup-method (ver mi artículo SPR-7431 y Creating prototype Spring beans on demand using lookup-method), de ahí la necesidad de setObject() artificial.

Si no te gustan los métodos/clases abstract, el método de búsqueda puede ser un método no abstracto no operativo o (mejor) la implementación predeterminada puede arrojar una excepción. Spring anulará la implementación en tiempo de ejecución, llamando efectivamente al getBean() por usted.

Bonificación: También traduje Executor/CompletionService a Spring managed beans. Tenga en cuenta que Spring admite estos out-of-the-box: Task Execution and Scheduling.

+0

Para la versión 3.0.5 de primavera que tenía que cambiar java.util.concurrent.CompletionService a java.util.concurrent.ExecutorCompletionService porque CompletionService es una interfaz, por lo que la instanciación no pudo tener éxito debido a la ambigüedad. –

0

Bueno, no estoy seguro de lo que piensas que Spring te va a comprar aquí, pero yo inyectaría una fábrica de algún tipo que escupe Runnable/Callable 's.

private final ExecutorService executorParsers = Executors.newFixedThreadPool(10); 

@Autowired 
private CallableFactory myCallableFactory = new MyCallableFactory(); //create this factory 

public void parse(List<MyObjInt> objs) { 
    //... bunch of elided stuff .... 

    CompletionService<AsupParseObj> parserService = new ExecutorCompletionService<AsupParseObj>(executorParsers); 

    for (final AsupStoreObj obj : objs) { 
     parserService.submit(myCallableFactory.createCallable(obj)); 
    } 
} 

También se puede inyectar el ExecutorService con la primavera también.

Cuestiones relacionadas