2013-02-27 14 views
12

Ho appena iniziato con il concetto Spring IOC. Spesso vedo la maggior parte degli esempi trovati in internet che usano il codice per ottenere l'oggetto.Come evitare l'uso di ApplicationContext.getBean() quando si implementa Spring IOC

ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml"); 
Hello hello = (Hello) appContext.getBean("hello"); 

Come riferimento da queste domande 1 e 2 in StackOverflow. Ho dedotto che non è necessario utilizzare appContext.getBean ("ciao") nel codice che è considerato una cattiva pratica. Inoltre, non consigliato più. Correggimi qui, se la mia inferenza è sbagliata.

Tenendo presente che ho apportato modifiche al mio progetto di conseguenza. Ecco la mia applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"> 
<bean id="utilClassRef" class="org.hd.derbyops.DUtils" lazy-init="false" /> 
<bean id="appContext" class="org.hd.derbyops.ContextProvider" lazy-init="false"> 
    <property name="utils" ref="utilClassRef" /> 
</bean> 
</beans> 

mio contextProvider Codice Classe

public class ContextProvider implements ApplicationContextAware { 

    private static ApplicationContext ctx; 

    /** 
    * Objects as properties 
    */ 
    private static DUtils utils; 

    public void setApplicationContext(ApplicationContext appContext) 
      throws BeansException { 
     ctx = appContext; 

    } 

    public static ApplicationContext getApplicationContext() { 
     return ctx; 
    } 

    public static DUtils getUtils() { 
     return utils; 
    } 

    public void setUtils(DUtils dUtilsRef) { 
     utils = dUtilsRef; 
    } 

} 

Per esempio, si consideri una classe A che dipende org.hd.derbyops.DUtils. Sto utilizzando la seguente riga di codice

ContextProvider.getUtils(); 

inorder per ottenere DUtils oggetto in classe A, evitando così l'utilizzo di ApplicationContext.getBean() ovunque nel mio codice.

Supponiamo, se ho 10 classi e la mia classe A dipende da tutti loro, i cui oggetti da creare e accedere senza utilizzare ApplicationContext.getBean(). Anche in questo caso, come sopra, ho pensato di creare proprietà della classe ContextProvider seguita da setter e getter di quella proprietà, dove in get<PropertyName> è statico. In questo modo, posso usarlo ovunque mi occorra un oggetto, come questo

ContextProvider.get<PropertyName>; 

Ecco la mia breve domanda. In primo luogo, il mio approccio è giusto? Se è giusto, caricando tutti i fagioli all'avvio, non sarebbe un killer delle prestazioni? Come lo faresti nelle tue applicazioni senza chiamare getBean almeno più di una volta?

Se si dovesse progettare un'applicazione Web &, si doveva implementare il CIO di primavera, senza utilizzare ApplicationContext.getBean() in alcun codice. Come lo faresti?

Nota: con riferimento alle altre domande tagged sopra

Calling ApplicationContext.getBean() non è Inversion of Control!

+0

Si sta utilizzando Spring MVC o cercando di usare servlet di base? –

+0

Non sto usando Spring MVC, lo sto usando solo per IOC – srk

+2

In generale, * qualcuno * avrà bisogno di ottenere un bean da 'ApplicationContext'. Idealmente, verrà chiamato una sola volta, e sarebbe dall'oggetto bootstrap ... –

risposta

9

Le risposte semplici sono sì e no, no e no. E infine, fai una ricerca online per MVC primaverile, poiché probabilmente questo è ciò che desideri.

Quindi, il tuo approccio. Sì, hai capito bene. Tuttavia, è considerata una pessima pratica usare metodi statici per tutto. E non è necessario. La primavera si basa sull'idea che puoi semplicemente creare dei pojos normali, e la primavera li userà come singleton e li inietterà l'uno nell'altro (può anche creare oggetti al volo, ma qui sto andando per il caso comune). Se si utilizzano classi e metodi statici:

  • Non è possibile prendere in giro i test dell'unità (si sta utilizzando JUnit giusto?)
  • Non si possono utilizzare con l'ereditarietà
  • inizializzatori statici sono un ottimo modo per perdere eccezioni
  • ecc, ecc

Quindi, sì a iniezione, e non a cose statica.

Avanti, prestazioni. Hai ragione, è molto più lento usare la molla, ma, se fai tutte le tue iniezione all'avvio, succede una volta sola. Spring è pensato per applicazioni lato server dove è probabile che ci sia un certo numero di classi singleton che passano dati in giro. Quindi, potrebbe esserci una classe per ottenere materiale da un DB, uno per elaborarlo e uno per visualizzarlo, e spring è usato per collegarli insieme.

Se si utilizza Spring in un'applicazione in cui si avvia ripetutamente, come un'applicazione della riga di comando, la si utilizza per il tipo di applicazione errato e probabilmente si desidera utilizzare un builder o qualcosa del genere. Spring è pensato per le grandi app aziendali che non vengono riavviate spesso.

Infine, se si inseriscono semplicemente tutte le dipendenze di una classe all'avvio, e lo si fa con tutte le classi, non è necessario eseguire alcuna operazione su getBean. Inoltre, l'utilizzo degli attributi init-method e destroy-method su un bean significa che è possibile avviare i processi una volta che Spring ha terminato le dipendenze di iniezione. Devi solo caricare il contesto e la tua app verrà generata (gioco di parole) nell'esistenza.

Come per i progetti Web, Spring MVC prende sostanzialmente l'intera inversione del modello di controllo e lo applica alle applicazioni Web. I contenuti primaverili vengono caricati dal contenitore e puoi definire gli URL a cui rispondere utilizzando nient'altro che i nomi di bean. E la maggior parte del tuo codice può rimanere come pojos. Se hai qualcosa di follemente complesso, potresti voler guardare il flusso della primavera, ma ti consiglio di assicurarti che il tuo spring foo sia molto forte prima di tentare di farlo.

+0

Nella mia azienda, non ho mai visto 'ApplicationContext.getBean()' e cose del genere. Ma questo è perché queste sono applicazioni web di livello aziendale. Quindi cosa carica esattamente tutte le mie lezioni per me? È il server che lo fa? – Kraken

+0

Normalmente si utilizza una delle classi di caricamento delle applicazioni Spring pre-inscatolate, che sono componenti JEE standard come servlet e quant'altro. Questi poi danno il via a tutte le cose primaverili del CIO. Nascosto nelle viscere di quelle classi, ci sarà una chiamata per creare il contesto dell'applicazione dal file XML, associarlo con l'applicazione attualmente in esecuzione e rendere il contesto dell'applicazione disponibile in qualche modo. – Jimadilo

1

Ecco il mio esempio per ottenere la prima istanza senza effettivamente chiamare getBean() su ApplicationContext.

public class Test{ 
    // Declare private static variable so that we can access it in main() 
    private static Triangle triangle; 

    // Use constructor injection to set the triangle 
    public Test(Triangle triangle) { 
     Test.triangle = triangle; 
    } 

    public static void main(String[] args) { 
     // Specify the context file containing the bean definitions 
     // Spring automatically creates instances of all the beans defined 
     // in this XML file. This process is performed before you actually make 
     // a getBean("beanName") call. 
     ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); 

     // Use instance methods of triangle 
     Test.triangle.draw(); 
    } 
} 

È possibile utilizzare un altro modo:

In spring.xml (il bean file XML di configurazione)

<bean class="com.example.Test" init-method="myMethod"> 
    <constructor-args ref="triangle"/> 
</bean> 

Ora per la classe principale

public class Test { 
    private final Triangle triangle; 

    public Test (Triangle triangle) { 
    this.triangle = triangle; 
    } 

    public static void main (String[] args) { 
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); 
    } 

    // Called by Spring immediately after the Triangle Bean has been created and 
    // all the properties for the bean have been set. This method name must match 
    // the one specified with destroy-method attribute in spring.xml 
    public void myMethod() { 
    triangle.draw(); 
    } 
} 
Problemi correlati