Spring 尝试 @Autowire 我的依赖项两次

Spring attempting to @Autowire my dependencies twice

我有一个 Spring MVC 应用程序,我在其中尝试在使用 @Controller 注释的 class 中使用 @Autowired。在没有 @Controller 注释的 classes 中,@Autowired 工作正常,一旦我添加 @Controller 注释,我在启动时得到一个巨大的堆栈跟踪,主要归结为 No qualifying bean of type [com.fasterxml.jackson.databind.ObjectMapper] found for dependency

我感觉到 Spring 正在尝试自动装配我的依赖项两次? 我将在我的问题中进一步证明......

在我的 web.xml 中,我正在加载我的 contextConfigLocation 和 DispatcherServlet:

....

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:META-INF/spring/applicationContext.xml</param-value>
</context-param>

....

<servlet>
    <servlet-name>ahpw-api</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/spring/webmvc-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>ahpw-api</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

....

webmvc-config.xml 仅包含允许我打开 Jackson JSON API:

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

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

    <mvc:default-servlet-handler/>

    <mvc:annotation-driven/>

    <!-- Cookies Filter to set cookies on JSON AJAX responses -->
    <mvc:interceptors>
        <bean id="cookieInterceptor" class="com.ahpw.api.controller.COOKIEFilter"/>
    </mvc:interceptors>

</beans>

在我的 applicationContext.xml 我有以下内容:

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

    <context:property-placeholder location="classpath*:META-INF/spring/*.properties"/>

    <context:spring-configured/>

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

    <!-- Setup Jackson instance -->
    <bean id="jackson" class="com.fasterxml.jackson.databind.ObjectMapper" />

    <!-- Setup RabbitMQ -->
    <bean id="nativeConnectionFactory" class="com.rabbitmq.client.ConnectionFactory">
        <property name="connectionTimeout" value="${rabbit.connection.timeout}"/>
        <property name="requestedHeartbeat" value="${rabbit.heartbeat}"/>
    </bean>
    <rabbit:connection-factory
            id="connectionFactory"
            port="${rabbit.port}"
            virtual-host="${rabbit.virtual}"
            host="${rabbit.host}"
            username="${rabbit.username}"
            password="${rabbit.password}"
            connection-factory="nativeConnectionFactory"/>
    <rabbit:admin connection-factory="connectionFactory"/>
    <rabbit:template id="amqpTemplate" connection-factory="connectionFactory" reply-timeout="${rabbit.rpc.timeout}" />


</beans>

我的class发生冲突的地方是这样开始的:

@Service
@Controller
@RequestMapping("/auth")
@JsonIgnoreProperties(ignoreUnknown = true)
public class AuthenticationController extends AbstractRPCPublisher<AuthenticationRequest, AuthenticationResponse> {

    @Autowired
    AmqpTemplate template;

    @Autowired
    ObjectMapper mapper;

如果我删除@Controller,一切都会正常启动,但显然 /auth 的请求映射停止工作。

如果我放回@Controller 并在 webmvc-config.xml 中复制 jackson bean 和 rabbitMQ 好东西,它启动时没有错误,但这意味着每个资源都有两个实例,两个 WEB 中的配置副本-INF 和 META-INF,不可取。

有没有办法通过 webmvc-config.xml 实例化我的控制器,但告诉它忽略 @Autowired 以便我的 applicationContext 可以处理它们,如果是这样,@Autowire 会正常运行吗?

您必须定义 ContextLoaderListener 侦听器,它将创建您的 Web 应用程序的根上下文并加载 <context-param> 标签中的 contextConfigLocation 定义:

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

因此 applicationContext.xml 应用程序上下文中定义的 bean 将可用于 webmvc-config.xml 应用程序上下文。

不知道是不是打错了,但是AuthenticationController class一定不要注解@Service@Controller就够了