在运行时使用@Scheduled注释创建spring bean

时间:2014-11-07 18:50:08

标签: java spring annotations osgi scheduled-tasks

我的用例如下:

我目前正在开发一个应用程序,其中有一个EventModule负责触发各种事件。其中一个事件是TimeEvent。这些时间事件应该每秒发射一次。在我的应用程序启动并运行时,还应该可以添加对新事件的支持。对于后一个要求,我正在使用OSGI。

为了自己生成时间事件,我发现spring已经为我提供了这样的功能,即将@Scheduled注释放在一个将被定期调用的方法上(在我的情况下每秒一次)。

所以我有这个代码:

/**
 * Generator class that periodically generates {@link TimeEvent}s.
 */
@Component
@EnableScheduling
public class TimeEventGenerator {

  @Scheduled( cron = "*/1 * * * * ?" )
  public void testSchedule() {
    // fire a time event
  }

}

这很好用,事件每秒都会触发。但是,这需要在启动时实例化TimeEventGenerator类(因为它使用@Component注释)。在我的用例中,即OSGI部分,每当我决定插入对start(BundleContext)的支持时,我应该能够在BundleActivator的{​​{1}}方法中创建此类的实例。 ,因此不能选择TimeEvents注释。

这是我遇到麻烦的部分。我了解到我可以使用@Component在spring应用程序上下文中自己注入bean,这正是我所做的,这导致了以下代码:

BeanFactoryPostProcessor

这里的问题是,每当我使用/** * Class that allows to add spring beans to a running application context. */ @Component public class RuntimeBeanFactory implements ApplicationContextAware, BeanFactoryPostProcessor { private ApplicationContext applicationContext; private ConfigurableListableBeanFactory beanFactory; @Override @Autowired public void setApplicationContext( ApplicationContext aApplicationContext ) throws BeansException { applicationContext = aApplicationContext; } @Override @Autowired public void postProcessBeanFactory( ConfigurableListableBeanFactory aBeanFactory ) throws BeansException { beanFactory = aBeanFactory; } public <T> T createBean( Class<T> aBeanClass, String aBeanName ) throws IOException { BeanDefinitionRegistry registry = ( ( BeanDefinitionRegistry ) beanFactory ); GenericBeanDefinition beanDefinition = new GenericBeanDefinition(); beanDefinition.setBeanClass( aBeanClass ); beanDefinition.setLazyInit( false ); beanDefinition.setAbstract( false ); beanDefinition.setAutowireCandidate( true ); if ( !registry.isBeanNameInUse( aBeanName ) ) { registry.registerBeanDefinition( aBeanName, beanDefinition ); } return applicationContext.getBean( aBeanClass ); } } 方法创建TimeEventGenerator(参见第一个代码段)时,永远不会调用createBean方法,而我预计它会是这样的,因为豆是由春天管理的。

编辑:我忘了添加我已经尝试了上面的代码,其中包含两个GenericBeanDefinition子类,即ScannedGenericBeanDefinition和AnnotatedGenericBeanDefinition,但没有成功。

2 个答案:

答案 0 :(得分:1)

查看Spring文档,我认为您应该尝试使用AnnotatedGenericBeanDefinition而不是GenericBeanDefinition。请参阅文档here

修改 我正在查看ScheduledAnnotationBeanPostProcessor的代码,我的注释正在处理中。我遇到的问题是,即使后处理器识别出计划任务,它也只使用任务执行程序一次计划任务。当我注册我的预定课程时,这已经发生了,因为它没有被调用。将刷新事件传递给后处理器会强制它进行调度,但它也会重新安排其他任务。查看代码(至少在Spring 3.2中),使用注释无法实现您想要做的事情。您可以创建自定义注释处理器并使用任务执行程序注册任务。

答案 1 :(得分:0)

如果你只是需要打开和关闭TimeEventGenerator,那么只需将它放在一个单独的包中,然后启动和停止包就可以打开和关闭它。