我正在运行Spring 3.2.3。RELEASE和我在@Service装饰类中有几个方法,它们是计划任务,因此用@Scheduled注释装饰。
所有的Spring bean都在容器中被检测和实例化,但是@Scheduled注释永远不会被调用。
我有几个应用程序上下文,但是主文件如下所述:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<import resource="classpath:core-properties.xml" />
<import resource="classpath:core-datasource.xml" />
<import resource="classpath:core-task-scheduler.xml" />
<context:component-scan base-package="com.atlaschase.project.core">
<context:exclude-filter type="regex"
expression="com.atlaschase.project.core.services.jms.*" />
<context:exclude-filter type="regex"
expression="com.atlaschase.project.core.services.processor.*" />
<context:exclude-filter type="regex"
expression="com.atlaschase.project.core.services.remote.*" />
<context:exclude-filter type="regex"
expression="com.atlaschase.project.core.bootstrap.populators.*" />
</context:component-scan>
<bean id="bufferPopulator" class="com.atlaschase.project.core.services.jms.buffer.BufferPopulator"/>
<bean id="eventBuffer" class="com.atlaschase.project.core.services.jms.buffer.EventBuffer"/>
<bean id="processorEventHandler" class="com.atlaschase.project.core.services.jms.buffer.ProcessorEventHandler"/>
另一个重要文件导入为"core-task-scheduler.xml"。配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="1"/>
<task:scheduler id="myScheduler" pool-size="5"/>
</beans>
最初,执行器引用(上面)是在主应用程序上下文中定义的,但在阅读了其他类似的问题已经以这种方式解决后,我将其作为导入分离出来。不幸的是,这并没有帮助。我还移动了导入声明,但这似乎没有效果。
在Spring应用程序上下文中直接声明计划的方法工作得很好——但是我非常热衷于使用注释。
下面是带注释的类:**
* Service that batches the saving of position updates into a periodically executed
* process.
*/
@Service
public class PositionAggregatorService {
static Logger logger = Logger.getLogger(AircraftPositionAggregatorService.class);
// The service will not execute within 1 minute of a previous batch attempt.
// This paramater is updated by a message from another node indicating that
// they are commencing a batch save of position updates.
private DateTime blockingTime;
private Map<Long, List<Position>> positions;
@Autowired
private PositionDao positionDao;
@Autowired
private InternalPublisher internalEventPublisher;
@PostConstruct
private void initialise(){
positions = new ConcurrentHashMap<Long, List<Position>>();
}
/*
* Scheduled to execute every 10 minutes as long current time is not
* before the blocking time threshold.
*
* */
@Scheduled(fixedRate=6000)
public void batchSavePositionUpdates(){
if(blockingTime != null){
if(DateTime.now(DateTimeZone.UTC).isBefore(blockingTime)){
return;
}
}
PositionPersistStartedNotification started = new PositionPersistStartedNotification(DateTime.now(DateTimeZone.UTC), DateTime.now(DateTimeZone.UTC).plusMinutes(2));
internalEventPublisher.publishPositionPersistStartedNotification(started);
DateTime mostRecentUpdateTime = null;
List<Position> positionsToSave = new ArrayList<Position>();
for(Long flightId : positions.keySet()){
List<Position> positionList = positions.get(flightId);
for(Position position : positionList){
if(mostRecentUpdateTime == null){
mostRecentUpdateTime = new DateTime(position.getTime());
}
else{
DateTime positionTime = new DateTime(position.getTime());
if(positionTime.isAfter(mostRecentUpdateTime)){
mostRecentUpdateTime = positionTime;
}
}
positionsToSave.add(position);
}
}
Boolean successfulSave = false;
try{
positionDao.save(positionsToSave);
successfulSave = true;
logger.info(positionsToSave.size() + " Position Updates saved successfully");
}catch(Exception exception){
logger.error("Failed to persist latest position updates to database");
logger.error(exception);
}
if(successfulSave){
removeSavedPositions(mostRecentUpdateTime);
PositionPersistEndedNotification ended = new PositionPersistEndedNotification(DateTime.now(DateTimeZone.UTC), mostRecentUpdateTime);
internalEventPublisher.publishPositionPersistEndedNotification(ended);
}
}
}
Spring上下文是否在运行时加载成功?我发现在xsd(3.0和3.2)中共存的不同版本的名称空间定义中存在一些不一致之处。您可以尝试在这些名称空间中保持一致的相同版本,然后再试一次吗?
应用程序正在通过监听上下文被加载,然后在ContextRefreshedEvent上执行一个方法来启动。
当我从应用程序中删除这个ApplicationEventListener并简单地调用bean上的公共方法来启动服务(而不是依赖于ApplicationEventListener)时,应用程序随后正常启动,所有@Scheduled注释都按预期工作。