Come raccogliere e inserire tutti i fagioli di un determinato tipo in Primavera XML di configurazione

Uno dei più forti accenti del framework Spring è il L’Iniezione Di Dipendenza concetto. Capisco uno dei consigli dietro che è quello di separare generale di alto livello meccanismo dettagli di basso livello (come annunciato da Dipendenza Inversione Di Principio).

Tecnicamente, che si riduce ad avere un fagiolo attuazione di sapere il meno possibile su di un bean di essere iniettato come una dipendenza, ad esempio,

public class PrintOutBean {
    private LogicBean logicBean;
    public void action() {
        System.out.println(logicBean.humanReadableDetails());
    }
    //...
}

<bean class="PrintOutBean">
    <property name="loginBean" ref="ShoppingCartBean"/>
</bean>

Ma che se volevo avere un alto livello di meccanismo operativo su più dipendente fagioli?

  public class MenuManagementBean {
       private Collection<Option> options;
       public void printOut() {
            for (Option option:options) {
              //do something for option
            }
            //...
       }
  }

So che una soluzione potrebbe essere quella di utilizzare @Autowired annotazione nel singleton bean, che è…

  @Autowired
  private Collection<Option> options;

Ma non viola il principio di separazione? Perché devo specificare che cosa dipendenti a prendere il posto di li uso (cioè MenuManagementBean classe nel mio esempio)?
C’è un modo per iniettare collezioni di fagioli di configurazione XML come questo (senza alcuna annotazione nel MMB classe)?

<bean class="MenuManagementBean">
    <property name="options">
       <xxx:autowire by-type="MyOptionImpl"/>
    </property>
 </bean>
  • Io non credo che l’aggiunta di @Autowired per il campo consente di creare la raccolta di opzioni per voi – c’è ancora bisogno di dichiarare un fagiolo nel tuo contesto che elenca le opzioni. E quindi si potrebbe benissimo cadere le @Autowired e mettere un <ref bean=”xxx”> nel MMB contesto definizione.
  • Sono abbastanza sicuro che l’aggiunta di @Autowired per una collezione che permette di raccogliere tutti i fagioli di raccolta tipo di elemento. Questo è come la usiamo per tutto il tempo. Spring 2.5 doc su di essa: static.springsource.org/spring/docs/2.5.x/reference/…
  • Ok, grande, Bella caratteristica! Ho fatto controllare i documenti, ma io non l’ho visto, quando ho guardato. Mi dispiace per la confusione.
  • Mi hanno riferito di una richiesta di funzionalità per la Primavera quadro di copertina: jira.springframework.org/browse/SPR-7183
  • Oledzki Non è esattamente correlato con la domanda, ma il Autowired di lavoro quando si utilizza Java posto la Configurazione del file XML? Sembra che non mi funzionano allo stesso modo. Penso che la Risorsa è che quando si utilizza la configurazione di Java, non Autowired.



3 Replies
  1. 27

    Non out-of-the-box la funzione per fare questo, no. Tuttavia, se si desidera un modo per raccogliere tutti i fagioli di un certo tipo in una raccolta senza l’uso di @Autowired elenco, quindi è facile scrivere un custom FactoryBean di farlo per voi:

    public class BeanListFactoryBean<T> extends AbstractFactoryBean<Collection<T>> {
    
        private Class<T> beanType;
        private @Autowired ListableBeanFactory beanFactory;
    
        @Required
        public void setBeanType(Class<T> beanType) {
            this.beanType = beanType;
        }
    
        @Override
        protected Collection<T> createInstance() throws Exception {
            return beanFactory.getBeansOfType(beanType).values();
        }
    
        @Override
        public Class<?> getObjectType() {
            return Collection.class;
        }    
    }

    e poi

     <bean class="MenuManagementBean">
        <property name="options">
           <bean class="BeanListFactoryBean">
              <property name="beanType" class="MyOptionImpl.class"/>
           </bean>
        </property>
     </bean>

    Tuttavia, questo sembra come un sacco di sforzo per evitare di mettere @Autowired originale classe. Non è molto di una violazione da parte della SoC, se è di tutti – non c’è compiltime dipendenza, e non è a conoscenza di dove il options sono provenienti da.

    • Personalizzato FactoryBean: A prima vista credo che questa soluzione non mi permette di specificare due (o più) di raccolte autowired per tipologia e per essere iniettato come un unico insieme. Non ho stato in questione, ma ho pensato che potrebbe essere utile.
    • Quando si tratta di SoC violazione: vedo il tuo punto, ma ho ancora pensare che ci sia qualcosa di male su di esso. Che cosa se mi è richiesto di sviluppare e fornire il livello elevato di fagioli (MenuManagementBean nel mio esempio) nella mia libreria e poi alcuni, a seconda del progetto dovrebbe essere in grado di utilizzare?
    • Iniettare la fabbrica di fagioli con Option.class piuttosto che MyOptionImpl.class, che si dovrebbe ottenere tutti i fagioli che implementa l’interfaccia.
    • Hmm… Forse non è vero che pratico, ma ho pensato che sarebbe utile se si potesse iniettare solo alcune implementazioni di Option interfaccia. Soprattutto se il Option interfaccia è abbastanza generale (ha un sacco di secondaria e classi).
    • OK, quindi modificare l’impostazione di fabbrica bean per prendere un elenco di tipi e rendere aggiungere tutti i fagioli di tali tipi della stessa collezione.
    • Mi piace. Che avrebbe funzionato.

  2. 35

    Vecchia questione e in Primavera 3.1 è possibile:

    public class PluginPrototypeTest extends ASpringWebTest {
      @Autowired
      Collection<IDummyRepo> repos;
    
      @Test
      public void cacheTest() {
        assertNotNull(repos);
        assertEquals(2, repos.size());
        for(IDummyRepo r: repos){
          System.out.println(r.getName());
        }
      }
    }
    
    @Repository
    public class DummyRepo implements IDummyRepo {
      @Override
      public String getName(){
        return "DummyRepo";
      }
    }
    @Repository
    public class DummyRepo2 implements IDummyRepo {
      @Override
      public String getName(){
        return "DummyRepo2";
      }
    }
    • Credo che la richiesta originale era quello di evitare l’uso di annotazioni, di non evitare l’uso di XML…

Lascia un commento