2013-01-02 5 views
1

J'ai quelques classes gérées par Spring (via la configuration xml), dont une SessionFactory, qui est injectée dans une autre classe gérée Spring. Chaque fois que cette classe a besoin d'une nouvelle session, elle appelle createSession sur la SessionFactory.Beans créés en usine non statiques et gérés en usine

Cependant, à moins que je ne me trompe, cela signifie que les sessions elles-mêmes ne sont pas gérées par Spring, ce qui est problématique car elles ont des méthodes @Transactional, qui nécessitent que le bean soit géré par Spring.

J'ai lu sur FactoryBeans, mais je ne suis pas sûr comment la meilleure façon de le faire est, d'autant plus que ma méthode createSession prend un paramètre, et le FactoryBean.getObject() ne le fait pas.

Je peux utiliser getObject, puis régler le paramètre manuellement plus haut, mais je voudrais forcer l'ensemble en usine si possible.

Quelqu'un peut-il aider? Merci d'avance. Un exemple simplifié est ci-dessous.

public class SessionFactory { 

    public final Session createSession(String username){ 
     Session session = new SessionImpl(username); 
     return session; 
    } 

} 


public class SessionImpl implements Session{ 

    private String username; 

    @Override 
    @Transactional 
    public void doSomething(){ 
     // Does something 
    } 

    public void setUsername(String username){ 
     this.username = username; 
    } 

    public String getUsername(){ 
     return username; 
    } 

} 


public class Service { 

    private SessionFactory sessionFactory; // Set by Spring through xml config 

    public void doSomethingServicy(){ 

    } 

    public void setSessionFactory(SessionFactory sessionFactory){ 
     this.sessionFactory = sessionFactory; 
    } 


} 

Répondre

1

Je l'ai résolu en créant le grain de l'usine au printemps et declaraing un objet Session-scope prototype avec un grain d'usine et la méthode d'usine comme on le voit ci-dessous:

<bean id="sessionFactory" class="com.SessionFactory" > 
     <property name="dependencyA" ref="dependencyA" /> 
     <property name="dependencyB" ref="dependencyB" /> 
</bean> 

<bean id=session" class="com.SessionImpl" factory-bean="sessionFactory" factory-method="createSession" scope="prototype" /> 

récupérer ensuite une nouvelle instance dans le code lorsque nécessaire:

Session session = (Session) applicationContext.getBean(SpringConstants.SESSION_BEAN_NAME, username); 

ici le nom d'utilisateur fait partie du paramètre de la méthode Object... qui fait les arguments qui se sont passés dans les usines createSession méthode

J'apprécie la structure du programme pourrait être mieux, mais étant donné les restrictions sur le code, il résout bien le problème.

1

Je dirais que vous avez l'annotation @Transactional au mauvais endroit.

Ce n'est pas une session qui devrait être transactionnelle; Il doit être appliqué aux méthodes de service basées sur l'interface qui répondent à vos cas d'utilisation. C'est l'idiome typique du printemps. Je recommande de le suivre.

+0

Merci, mais malheureusement ce n'est pas une option actuellement, pouvez-vous suggérer une solution à ce problème? – TheBloodGuy

+0

Je l'ai déjà fait. C'est une option. Vas-y avec. Ou n'utilisez pas les transactions Spring. – duffymo

+0

Ma question ne concerne pas si @Transactional est au bon endroit ou pas, mais si je peux obtenir des beans Spring de l'usine. J'ai précisé que déplacer l'annotation n'est pas une option, car ce problème implique un code hérité et une restriction que je ne peux pas le changer. – TheBloodGuy