2010-11-25 2 views
4

À l'heure actuelle, j'ai un bean avec une méthode @Scheduled fonctionne bien; c'est déclaré dans mon applicationContext.xml.Comment planifier une nouvelle méthode dans une application Web Spring au moment de l'exécution?

<!-- some JPA stuff --> 

<bean id="aWorkingBean" class="some.package.WorkingBean"> 
    <property name="someDAO" ref="someDAO" /> 
</bean> 

<task:annotation-driven scheduler="myScheduler" /> 
<task:scheduler id="myScheduler" pool-size="10" /> 

Ce que je suis en train de faire est de planifier une autre méthode par programmation (chargement par exemple une classe annotée et injectent ses dépendances) sur demande. Quelque chose comme:

WebApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); 
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(NonWorkingBean.class); 
// add DAO references... 
ctx.registerBeanDefinition("nonWorkingBean", builder.getBeanDefinition()); // <-- this doesn't work 

Il est évident que cela ne fonctionne pas parce que le XmlWebApplicationContext est en lecture seule et n'a pas méthode registerBeanDefinition. Y a-t-il un autre moyen d'y parvenir?

J'utilise Tomcat 6.0.29 et 3.0.4 Spring

Répondre

3

<task:scheduler> et @Scheduled est vraiment juste une approche pratique pour la planification des tâches statiques. Ce n'est pas vraiment adapté à la planification dynamique. Oui, vous pouvez le faire fonctionner, mais ça va être gênant.

Lorsque vous mettez <task:scheduler id="myScheduler"> dans votre configuration, Spring crée un haricot TaskScheduler appelé . Cela peut être injecté dans vos propres beans, et peut être invoqué par programme afin de planifier de nouvelles tâches. Vous devrez créer un Runnable pour passer au TaskScheduler, mais cela devrait être assez simple.

+0

Merci! En fait, j'ai réussi à planifier de nouvelles tâches en obtenant le bean myScheduler et en utilisant Runnable, comme vous venez de le dire, mais je me demandais si c'était sûr pour a) les transactions et b) les fuites de threads. (Ma méthode planifiée utilise certains DAO). – arturo

0

Il y a plusieurs façons de le faire, mais vous le feriez habituellement utiliser un AutowireCapableBeanFactory.

est ici une façon de le faire:

final WebApplicationContext ctx = 
    ContextLoader.getCurrentWebApplicationContext(); 

// create the object yourself 
// and inject the dependenices you want manually 
final Object existingBean = initializeYourObjectHere(); 

AutowireCapableBeanFactory beanFactory = ctx.getAutowireCapableBeanFactory(); 

// now autowire it, injecting the remaining dependencies 
beanFactory.autowireBeanProperties(
    existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true); 

// run post processors and register bean under this name 
beanFactory.initializeBean(existingBean, "newBeanName"); 
+0

Merci pour votre réponse, mais j'ai une autre question: si the existingBean a une méthode @Scheduled, est-ce censé être automatiquement programmé? Aussi, après l'initialisation du bean, quand j'appelle ctx.getBean ("newBeanName") lance NoSuchBeanDefinitionException – arturo

+0

a) si le post-processeur pour @Scheduled est enregistré, oui. b) vous devrez peut-être d'abord rafraîchir le contexte –

+0

Désolé, bien que votre suggestion soit très bonne, je suis toujours coincé avec ceci: a) en ce qui concerne le post-processeur, n'est-ce pas assez? b) est-il sécuritaire de rafraîchir le contexte même si j'ai l'affaire JPA? – arturo

Questions connexes