Est-il possible de créer une fabrique ou un proxy qui peut décider si le thread s'exécute dans une demande (Web) ou un processus de fond (par exemple.) puis en fonction de ces informations, il crée un bean session ou un bean prototype?Spring: le binaire Inject dépendait du contexte (processus session/web ou thread/arrière-plan local)
Exemple (pseudo config Spring :)
<bean id="userInfoSession" scope="session" />
<bean id="userInfoStatic" scope="prototype" />
<bean id="currentUserInfoFactory" />
<bean id="someService" class="...">
<property name="userInfo" ref="currentUserInfoFactory.getCurrentUserInfo()" />
</bean>
J'espère que cela ma question plus facile à comprendre ...
Ma solution
Il est jamais trop tard pour mettre à jour ses propres questions;). Je l'ai résolu avec deux instances différentes de session client, une session client SessionScoped et une session SingletonScoped. Les deux sont des haricots normaux.
<bean id="sessionScopedClientSession" class="com.company.product.session.SessionScopedClientSession" scope="session">
<aop:scoped-proxy />
</bean>
<bean id="singletonScopedClientSession" class="com.company.product.session.SingletonScopedClientSession" />
<bean id="clientSession" class="com.company.product.session.ClientSession">
<property name="sessionScopedClientSessionBeanName" value="sessionScopedClientSession" />
<property name="singletonScopedClientSessionBeanName" value="singletonScopedClientSession" />
</bean>
Le ClientSession alors décider si la portée singleton ou session:
private IClientSession getSessionAwareClientData() {
String beanName = (isInSessionContext() ? sessionScopedClientSessionBeanName : singletonScopedClientSessionBeanName);
return (IClientSession) ApplicationContextProvider.getApplicationContext().getBean(beanName);
}
où le type de session pourrait être recueillie par ceci:
private boolean isInSessionContext() {
return RequestContextHolder.getRequestAttributes() != null;
}
Toutes les classes implémentent une interface appelée IClientSession. Les beans singletonScoped et sessionScoped s'étendent d'une BaseClientSession où l'implémentation est trouvée.
Chaque service peut alors utiliser la session client-à-dire:
@Resource
private ClientSession clientSession;
...
public void doSomething() {
Long orgId = clientSession.getSomethingFromSession();
}
Maintenant, si nous allons un peu plus loin, nous pouvons écrire quelque chose comme un émulateur pour la session. Cela peut être fait en initialisant la session clientSession (qui n'est dans aucun contexte d'une requête) la session singleton. Maintenant, tous les services peuvent utiliser le même clientSession et nous pouvons encore « imiter » un utilisateur à savoir:
clientSessionEmulator.startEmulateUser(testUser);
try {
service.doSomething();
} finally {
clientSessionEmulator.stopEmulation();
}
Un autre conseil: prendre soin de filetage en SingletonScoped clientSession exemple! Wouw, je pensais que je pourrais le faire avec moins de lignes;) Si vous aimez en savoir plus sur cette approche, n'hésitez pas à me contacter.
Je vais essayer. Parfois, la solution la plus simple est la meilleure et si cela fonctionne, pourquoi n'est-ce pas soigné? D'autres solutions? –
@Frank: Le code qui utilise 'RequestContextHolder' est généralement difficile à tester. Pour cette raison, il devrait être découragé. – skaffman