我的用例如下:
我目前正在开发一个应用程序,其中有一个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,但没有成功。
答案 0 :(得分:1)
查看Spring文档,我认为您应该尝试使用AnnotatedGenericBeanDefinition而不是GenericBeanDefinition。请参阅文档here。
修改强>
我正在查看ScheduledAnnotationBeanPostProcessor
的代码,我的注释正在处理中。我遇到的问题是,即使后处理器识别出计划任务,它也只使用任务执行程序一次计划任务。当我注册我的预定课程时,这已经发生了,因为它没有被调用。将刷新事件传递给后处理器会强制它进行调度,但它也会重新安排其他任务。查看代码(至少在Spring 3.2中),使用注释无法实现您想要做的事情。您可以创建自定义注释处理器并使用任务执行程序注册任务。
答案 1 :(得分:0)
如果你只是需要打开和关闭TimeEventGenerator,那么只需将它放在一个单独的包中,然后启动和停止包就可以打开和关闭它。