2013-05-01 17 views
38

Ho il DataPrepareService che prepara i dati per i report e ho un Enum con tipi di report, e ho bisogno di iniettare ReportService in Enum o avere accesso a ReportService da enum.Inject bean in enum

mio servizio:

@Service 
public class DataPrepareService { 
    // my service 
} 

mio enum:

public enum ReportType { 

    REPORT_1("name", "filename"), 
    REPORT_2("name", "filename"), 
    REPORT_3("name", "filename") 

    public abstract Map<String, Object> getSpecificParams(); 

    public Map<String, Object> getCommonParams(){ 
     // some code that requires service 
    } 
} 

Ho cercato di usare

@Autowired 
DataPrepareService dataPrepareService; 

, ma non ha funzionato

Come posso inserire il mio servizio in enum?

risposta

8

Forse qualcosa di simile:

public enum ReportType { 
    @Component 
    public class ReportTypeServiceInjector { 
     @Autowired 
     private DataPrepareService dataPrepareService; 

     @PostConstruct 
     public void postConstruct() { 
      for (ReportType rt : EnumSet.allOf(ReportType.class)) 
       rt.setDataPrepareService(dataPrepareService); 
     } 
    } 

    REPORT_1("name", "filename"), 
    REPORT_2("name", "filename"), 
    ... 
} 
+1

downvote per non compilare – Pranalee

+0

il tuo dovrebbe cambiare classe interna a classe statica –

1

sarà difficile da controllare che il contenitore della molla è già installato e funzionante al momento della enum viene creata un'istanza (se si ha una variabile con questo tipo in un test -case, il tuo contenitore di solito non sarà lì, anche l'aspetto di autowiring non aiuterà in questo caso). Vorrei raccomandare semplicemente di lasciare che il servizio dataprepare o qualcosa ti fornisca i parametri specifici con un metodo di ricerca con il parametro enum.

38
public enum ReportType { 
    @Component 
    public static class ReportTypeServiceInjector { 
     @Autowired 
     private DataPrepareService dataPrepareService; 

     @PostConstruct 
     public void postConstruct() { 
      for (ReportType rt : EnumSet.allOf(ReportType.class)) 
       rt.setDataPrepareService(dataPrepareService); 
     } 
    } 

    REPORT_1("name", "filename"), 
    REPORT_2("name", "filename"), 
    ... 
} 

weekens' answer lavori Se si cambia classe interna alla statico in modo primavera possano vederlo

+1

Si salva la mia giornata. Grazie! –

+1

Qualcosa da notare qui, il codice sopra non verrà compilato perché la classe statica è definita prima delle costanti enum. Secondo le specifiche java le costanti enum vengono prima di ogni dichiarazione di classe. Metti semplicemente le costanti in alto e la tua classe in basso. – prettyvoid

0

Enum s sono statici, quindi bisogna trovare un modo per accedere ai fagioli da un contesto statico.

È possibile creare una classe denominata ApplicationContextProvider che implementa l'interfaccia ApplicationContextAware.

import org.springframework.beans.BeansException; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.ApplicationContextAware; 

public class ApplicationContextProvider implements ApplicationContextAware{ 

private static ApplicationContext appContext = null; 

public static ApplicationContext getApplicationContext() { 
    return appContext; 
} 

public void setApplicationContext(ApplicationContext appContext) throws BeansException { 
    this.appContext = appContext; 
} 
} 

quindi aggiungere questo file vostro contesto di applicazione:

<bean id="applicationContextProvider" class="xxx.xxx.ApplicationContextProvider"></bean> 

dopo che si poteva accedere al contesto di applicazione in modo statico come questo:

ApplicationContext appContext = ApplicationContextProvider.getApplicationContext(); 
0

Penso che questo quello che necessario

public enum MyEnum { 
    ONE,TWO,THREE; 
} 

Autowire enum come al solito

@Configurable 
public class MySpringConfiguredClass { 

      @Autowired 
     @Qualifier("mine") 
      private MyEnum myEnum; 

} 

Ecco il trucco, utilizzare la fabbrica-method = "valueOf" e anche fare in modo lazy-init = "false"

così il contenitore crea il fagiolo in anticipo

<bean id="mine" class="foo.bar.MyEnum" factory-method="valueOf" lazy-init="false"> 
    <constructor-arg value="ONE" /> 
</bean> 

e il gioco è fatto!