如果应用于两个线程之间共享的bean,则@Autowired不起作用

时间:2012-05-03 17:06:09

标签: java multithreading synchronization spring-3 autowired

我在一个非常基本的场景中遇到了一些麻烦:我有一个java web应用程序(第3版),我想将一些对象存储到堆栈中。然后我想用调度程序管理堆栈中的对象,所以我实现了一个石英作业。干净利落。我使用@Autowired注释在第一个服务类和作业类中注入堆栈。对于服务类,表成功注入,但对于作业类,表为空。 这是代码:

要分享的课程

package it.unifi.det.telemat.vr.data;
@Component
public class IndexedNodesStack extends HashMap<IndexedObject, Boolean>{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Override
    public synchronized int size() {
        // TODO Auto-generated method stub
        return super.size();
    }

    //all the HashMap methods are implemented in a synchronized wrapper method

}

第一堂课(@Autowired成功)

package it.unifi.det.telemat.vr.service;
@Service
public class InnerNodeManager extends ConcreteNodeManager{

    @Autowired
    private IndexedNodesStack indexedNodesStack; //<--- it is actually autowired!


    private void manageIndexedNodes(Boolean isPut, String lri, String features)
    {
        IndexedObject indexedObject = new IndexedObject();
        indexedObject.setId(lri);
        if(features != null && isPut)
            indexedObject.generateFeatures(features);

        indexedNodesStack.put(indexedObject, isPut);
    }

}

工作类(@Autowired失败)

package it.unifi.det.telemat.vr.service.scheduler;
@Component
public class QuartzJSearchJob extends QuartzJobBean{

    @Autowired
    private IndexedNodesStack indexedNodesStack; //<--- this variable is null :-(

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException
    {
        //do work       
    }
}

编辑:这里是servlet.xml

<context:component-scan base-package="it.unifi.det.telemat.vr" />

<bean name="searchJob"
class="org.springframework.scheduling.quartz.JobDetailBean">
    <property name="jobClass" value="it.unifi.det.telemat.vr.service.scheduler.QuartzJSearchJob" />
</bean>

<bean id="searchJobTrigger"
class="org.springframework.scheduling.quartz.CronTriggerBean">
    <property name="jobDetail" ref="searchJob" />
    <property name="cronExpression" value="0/50 * * * * ?" />
</bean>

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
    <list>
        <ref bean="searchJobTrigger" />
        </list>
    </property>
</bean>

也许我对线程之间的资源共享缺乏一些了解,因为这是我在这个领域的第一次尝试。 我错过了什么?

6 个答案:

答案 0 :(得分:2)

自动装配仅在从Spring bean工厂创建bean时才有效。您是否在不使用bean工厂的情况下创建了对象,即使用new QuartzJSearchJob()语法创建它?

答案 1 :(得分:2)

好的,最后我明白了。 它不起作用因为spring没有实例化quartzJSearchJob,石英确实如此。要在作业内注入的bean必须通过SchedulerFacoryBean传递。 这是使事情有效的配置。

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
        <list>
            <ref bean="searchJobTrigger" />
        </list>
    </property>
    <property name="schedulerContextAsMap">
    <map>
       <entry key="indexedNodesStack" value-ref="indexedNodesStack" />
    </map>
    </property>
</bean>

答案 2 :(得分:0)

QuartzJSearchJob未被识别为bean,因为它没有类级别注释。试试@Component

答案 3 :(得分:0)

您忘记了“jobDetails”属性:

<property name="jobDetails">
    <list>
        <ref bean="searchJob" />
    </list>
</property>

您还需要使用org.springframework.scheduling.quartz.JobDetailFactoryBean代替org.springframework.scheduling.quartz.JobDetailBean

像这样插入:

<bean name="searchJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    <property name="jobClass" value="it.unifi.det.telemat.vr.service.scheduler.QuartzJSearchJob" />
</bean>

<bean id="searchJobTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
    <property name="jobDetail" ref="searchJob" />
    <property name="cronExpression" value="0/50 * * * * ?" />
</bean>

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
        <list>
            <ref bean="searchJobTrigger" />
        </list>
    </property>
    <property name="jobDetails">
        <list>
            <ref bean="searchJob" />
        </list>
    </property>
</bean>

答案 4 :(得分:0)

我遇到同样的问题,我通过将SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);添加为Job.execute(JobExecutionContext context)方法的第一行来解决此问题。

答案 5 :(得分:-2)

我认为您必须在scheduleFactoryBeansetSchedulerContextAsMap()中指定一个值,然后将对象放入此地图中,然后才能生效。

@Bean(name = "scheduler")
  public SchedulerFactoryBean schedulerFactory()
  {
    SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
    schedulerFactory.setDataSource(dataSource);
    schedulerFactory.setAutoStartup(true);
    schedulerFactory.setGlobalJobListeners(globalJobListeners);
    schedulerFactory.setSchedulerContextAsMap(contextMap());
    schedulerFactory.setQuartzProperties(schedulerProperties());
    return schedulerFactory;
  }