2009-07-20 3 views
6

J'ai une application qui a plusieurs écrans et chaque écran est sélectionné via un bouton. Chaque écran contient des composants assez lourds, il est donc important que seul l'écran d'activation soit en mémoire - tous les autres devraient être disponibles pour la récupération de place.Utilisation de getBean par opposition à l'injection de méthode au printemps

L'application utilise ressort pour la colle et actuellement il commute les écrans à l'aide de getBean():

//event handler for a specific button 
public void actionPerformed(Event e) { 
    setScreen((Screen) applicationContext.getBean("screen1")); 
} 

« screen1 » est un grain de prototype de sorte qu'une nouvelle instance de l'écran est créé lorsque le bouton est enfoncé. En outre, setScreen() est le seul endroit où une référence à Screen est maintenue dans l'application, de sorte que l'écran précédemment actif sera disponible pour la récupération de place. Je ne l'ai pas encore testé mais je m'attends à ce que ça fonctionne bien - pas de science de fusée ici! Le problème est - après avoir lu this page sur pourquoi getBean() est considéré comme mauvais - je me demande s'il existe une façon plus idiomatique d'obtenir les mêmes résultats tout en supprimant la dépendance sur getBean().

J'ai examiné l'injection de méthode et il me semble introduire la complexité avec peu d'avantages. C'est un autre concept à apprendre, plus magique, qui ajoute une dépendance à CGLIB, etc. Si je veux vraiment supprimer la dépendance à Spring, je peux simplement introduire une interface qui expose la méthode getBean().

Est-ce que getBean() et l'injection de méthode sont les seules options dans mon cas ou ai-je manqué quelque chose?

Et si oui, getBean() est-il vraiment si mauvais?

Répondre

0

Avez-vous envisagé une approche d'usine?

public interface ComponentFactory<T> { 
    T create(); 
} 

public class ScreenFactory implements ComponentFactory<Screen> { 
    @Override 
    Screen create() { ... } 
} 

public class MyApp { 
    private ComponentFactory<Screen> screen1; 

    public void actionPerformed(Event e) { 
    setScreen(screen1.create()); 
    } 

    public void setScreen1(ComponentFactory<Screen> screen1) { 
    this.screen1 = screen1; 
    } 

    private void setScreen(Screen screen) { ... } 
} 

combiné avec:

<bean id="screenFactory" class="com.myclass.ScreenFactory"/> 

<bean id="myapp" class="..."> 
    <property name="screen1" ref="screenFactory"/> 
</bean> 

Vous pouvez l'auto-fil de cours ci-dessus. Le problème avec ce que vous faites est qu'il code à la fois le bean que vous instanciez et attache votre implémentation à ApplicationContext. Si vous avez besoin de vous moquer et/ou de tester vos applications/composants, cela rendra votre vie incroyablement difficile. La solution d'usine ci-dessus la rendra triviale.

+0

Donc dans votre solution, getbean() est invoqué dans la méthode factory create(), n'est-ce pas? –

+0

Pas exactement. Il est remplacé par une méthode d'usine, mais il est beaucoup plus facile de se moquer de l'interface ci-dessus que de se moquer d'un contexte d'application. Plus c'est branché. En fin de compte, il s'agit d'une implémentation un peu plus simple de l'injection de méthode de Spring http://static.springsource.org/spring/docs/2.5.x/reference/beans.html # beans-factory-lookup-méthode-injection – cletus

+0

Je vois, mais d'où vient la méthode factory create() obtenir son instance de l'écran? –

3

L'injection Setter, l'injection de propriétés ou l'injection de constructeurs créent toutes une application faiblement couplée qui est beaucoup plus facile à tester en se moquant. Il empêche également l'une de vos classes d'avoir des dépendances directes sur les classes Spring (ou autre conteneur IoC). Cela finit par être une solution globale plus propre lorsque vous n'avez pas à appeler manuellement getBean().

Je pense que vous devriez vous familiariser avec la notion de configuration des dépendances. La "magie" n'est pas du tout magique et c'est juste quelque chose avec lequel vous serez à l'aise quand vous l'utiliserez.

+0

Je parle de l'injection de méthode en utilisant l'étiquette de méthode de recherche qui diffère de l'injection de dépendances "standard" - c'est une caractéristique distincte qui dépend de l'AOP (et donc du CGLIB) et de ce qu'elle vous donne en usine. Cletus a démontré?) –

+0

L'usine isolera votre dépendance à Spring, mais elle devient ce que je pense être juste du code inutile à maintenir. Quel est le problème avec AOP? AOP est juste un détail de mise en œuvre de la façon dont Spring fait DI. – geofflane

0

Si vous voulez simplement vous débarrasser de getBean, pensez à utiliser un ServiceLocatorFactoryBean. Mais cela dépend de l'origine de la chaîne "screen1" dans votre application.

Questions connexes