Spring @Autowired 在没有上下文的情况下工作:annotation-config [重复]

Posted

技术标签:

【中文标题】Spring @Autowired 在没有上下文的情况下工作:annotation-config [重复]【英文标题】:Spring @Autowired working without context:annotation-config [duplicate] 【发布时间】:2014-02-24 07:05:45 【问题描述】:

如果应用程序上下文 xml 文件中缺少 context:annotation-config 元素,我已经测试了自动连接的行为。令我惊讶的是,它的工作原理是一样的。

所以这是我的问题: 即使应用程序上下文配置文件中缺少 context:annotation-config 元素,或者还有什么机制使此配置工作,为什么 AutowiredAnnotationBeanPostProcessor 会在 ApplicationContext 中注册?

我正在使用 Spring 版本 3.0.6.RELEASE 这是项目pom文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-    v4_0_0.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.springframework.samples.spring</groupId>
    <artifactId>spring-utility</artifactId>
    <version>1.0.0.CI-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>Spring Utility</name>
    <url>http://www.springframework.org</url>
    <description>
        <![CDATA[
  This project is a minimal jar utility with Spring configuration.
]]>
    </description>
    <properties>
        <maven.test.failure.ignore>true</maven.test.failure.ignore>
        <spring.framework.version>3.0.6.RELEASE</spring.framework.version>
    </properties>   
<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>$spring.framework.version</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>$spring.framework.version</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.14</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>

        </plugins>
    </build> 
</project>

这是应用上下文配置文件,context:annotation-config 元素被注释掉了:

<?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"
    xsi:schemaLocation="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">

    <description>Example configuration to get you started.</description>

    <!-- context:annotation-config/ -->

    <context:component-scan base-package="com.foo.ch04" />

</beans>

一个 MessageProvider,将被依赖的 bean MessageRenderer 用作协作者

package com.foo.ch04.helloworld;

import org.springframework.stereotype.Service;

@Service("messageProvider")
public class HelloWorldMessageProvider implements MessageProvider 

    public String getMessage() 
        return "Hello, World!";
    


MessageRenderer,其依赖 messageProvider 被自动注入:

package com.foo.ch04.helloworld;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("messageRenderer")
public class StandardOutMessageRenderer implements MessageRenderer 

    private MessageProvider messageProvider;

    public void render() 
        if (messageProvider == null) 
            throw new RuntimeException(
                    "You must set the property messageProvider before rendering     message.");
        
        System.out.println(messageProvider.getMessage());
    

    @Autowired
    public void setMessageProvider(MessageProvider provider) 
        messageProvider = provider;
    

    public MessageProvider getMessageProvider() 
        return messageProvider;
    

    

测试应用加载应用上下文并测试messageRenderer:

package com.foo.ch04.helloworld;

import org.springframework.context.support.GenericXmlApplicationContext;

public class DeclareSpringComponents 

    public static void main(String[] args) 
        GenericXmlApplicationContext context = new GenericXmlApplicationContext();
        context.load("classpath:META-INF/spring/app-context-annotation.xml");
        context.refresh();

        MessageRenderer renderer = context.getBean("messageRenderer",
                MessageRenderer.class);
        renderer.render();
    


即使应用程序上下文配置文件中缺少 ,消息“Hello, World!”在应用程序运行时写入标准输出。

【问题讨论】:

它们的功能是重叠的。看看这个类似的问题:annotation-config vs component-scan 【参考方案1】:

&lt;context:component-scan /&gt; 的使用意味着基于注解的配置,因此指定 &lt;context:annotation-config/&gt; 是多余的。

【讨论】:

我读过spring帮助文档,-->在扫描的包中扮演的角色,很有用如果我们想要 Autowire 未使用组件扫描定义的外部 bean。你能推荐一下这位先生吗?【参考方案2】:

'context:annotation-config' 这个 annotation-config 标记用于处理在应用程序上下文 XML 文件中声明的自动连接 bean。如果可以使用 'context:component-scan' 标签的范围发现自动连接的 bean,则无需使用 'context:annotation-config' 标签

【讨论】:

以上是关于Spring @Autowired 在没有上下文的情况下工作:annotation-config [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Spring 梳理 - @Autowired VS @Resource

如何在 JUnit 中加载应用程序上下文并使用 Autowired

@autowired和@resouce注入顺序

autowired和resource的区别

Spring Autowired空指针异常

Bean的自动装配(Autowired)