2013-08-22 55 views
1

我无法将@Service bean注入到QuartzJobBean中。使用this question的技巧,我能够注入@Repository bean,但不能注入@Service bean。下面是我有:未能将@Service bean注入到QuartzJobBean中

一个仓库bean来访问MongoDB的文件:

public interface MyRepository extends MongoRepository<> {} 

A服务bean来执行业务逻辑:

@Service 
public class MyService { 
    @Autowired 
    private MyRepository myRepository; 

    public void method1() { ... } 
} 

我能够使用的MyService从Spring MVC控制器,所以我知道Spring正确地实例化了它们。

接下来,我创建了一个从QuartzJobBean延伸,并尝试注入的MyService到它工作:

<bean name="myJob" class="org.springframework.scheduling.quartz.JobDetailBean"> 
     <property name="jobClass" value="com.MyJob" /> 
    </bean> 
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> 
     [jobDetails and triggers omitted] 
     <property name="schedulerContextAsMap"> 
     <map> 
      <entry key="myService"> 
       <ref bean="myService"/> 
      </entry> 

     </map> 
    </property> 
    </bean> 

有了这个配置,我'BeanCreationException: Cannot resolve reference to bean 'myService' while setting bean property 'schedulerContextAsMap'

如果我在schedulerContextAsMap改变“为myService”到' myRepository'它的工作。但是,我不想重新实现QuartzJobBean中的业务逻辑。

为什么myService bean对SchedulerFactoryBean不可见?顺便说一句,我已经启用了注释配置和组件扫描标签。

[更新 - 上下文初始化] 这里是我的web.xml,你可以看到spring-quartz.xml被最后引用了,所以一切都应该在它之前被初始化,不是吗?

<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value> 
     /WEB-INF/spring/root-context.xml, 
     /WEB-INF/spring/spring-security.xml, 
     /WEB-INF/spring/spring-quartz.xml 
     </param-value> 
    </context-param> 
    <listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 
    <servlet> 
    <servlet-name>appServlet</servlet-name> 
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <init-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value> 
     </init-param> 
    <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
    <servlet-name>appServlet</servlet-name> 
    <url-pattern>/</url-pattern> 
    </servlet-mapping> 

根的context.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:mongo="http://www.springframework.org/schema/data/mongo" 
xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
    http://www.springframework.org/schema/data/mongo 
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd"> 

<!-- Root Context: defines shared resources visible to all other web components --> 
<!-- Factory bean that creates the Mongo instance --> 
<bean id="mongo" class="org.springframework.data.mongodb.core.MongoFactoryBean"> 
    <property name="host" value="localhost" /> 
</bean> 

<!-- MongoTemplate for connecting and quering the documents in the database --> 
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> 
    <constructor-arg name="mongo" ref="mongo" /> 
    <constructor-arg name="databaseName" value="test" /> 
</bean> 

<!-- Use this post processor to translate any MongoExceptions thrown in @Repository annotated classes --> 
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" /> 

<mongo:repositories base-package="com.repositories" /> 

</beans> 

的servlet-context.xml的

<?xml version="1.0" encoding="UTF-8"?> 
<beans:beans xmlns="http://www.springframework.org/schema/mvc" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:beans="http://www.springframework.org/schema/beans" 
xsi:schemaLocation=" 
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd 
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> 

<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure --> 

<!-- Enables the Spring MVC @Controller programming model --> 
<annotation-driven conversion-service="conversionService"> 
    <argument-resolvers> 
     <beans:bean class="org.springframework.mvc.data.CustomArgumentResolver"/>   
     <beans:bean class="org.springframework.data.web.PageableArgumentResolver" /> 
    </argument-resolvers> 
</annotation-driven> 

<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources/ directory --> 
<resources mapping="/resources/**" location="/resources/" /> 

<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory --> 
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
    <beans:property name="prefix" value="/WEB-INF/views/" /> 
    <beans:property name="suffix" value=".jsp" /> 
</beans:bean> 

<!-- Only needed because we install custom converters to support the examples in the org.springframewok.samples.mvc.convert package --> 
<beans:bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> 
    <beans:property name="formatters"> 
     <beans:bean class="org.springframework.mvc.convert.MaskFormatAnnotationFormatterFactory" /> 
    </beans:property> 
</beans:bean> 

<!-- Only needed because we require fileupload in the org.springframework.samples.mvc.fileupload package --> 
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" /> 

<context:annotation-config /> 
<context:component-scan base-package="com" /> 
</beans:beans> 
+1

如何,什么时候初始化应用程序上下文(S)?根据你的问题,最有可能的调度程序在实例化服务的上下文之前在上下文中被实例化。编辑您的问题以提供有关如何初始化上下文的详细信息。 – kaliatech

+0

你说得对。我移动了我的spring-quartz.xml文件,现在schedulerFactory能够看到服务引用。谢谢。 – azgolfer

回答

0

看来,如果你已经解决了每个您的评论的问题,你的问题。但是,请注意:

底层的原始问题是您只在servlet-context中配置了组件扫描。因此,只有当servlet上下文被初始化时,MyService注释才会被处理。当ContextLoaderListener为root上下文处理spring-quartz.xml时,它还不可用。

如果您对服务等使用注释,但您可能希望在root-context.xml中启用组件扫描,但是可以过滤掉servlet中的组件扫描所获取的任何内容(例如控制器)上下文,以便您不会获得重复的初始化。

如果您的服务和Web代码共享公用包名称,那么常见的模式是使用过滤器,组件将扫描除控制器以外的所有内容扫描到根上下文中,然后仅扫描servet上下文中的控制器(和servlet)是这样的:

根的context.xml

<context:component-scan base-package="package"> 
    <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/> 
</context:component-scan> 

的servlet上下文。xml

<context:component-scan base-package="package" use-default-filters="false"> 
    <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation" /> 
</context:component-scan> 

当然,还有很多其他的选择。欲了解更多信息:

+0

很好的建议,谢谢你的提示。 – azgolfer