我在读spring 3.0。x参考文档来理解Spring Autowired注释:

3.9.2 @Autowired和@Inject

我不能理解下面的例子。我们需要在XML中做些什么来让它工作吗?

示例1

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Autowired
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...
}

示例2

public class MovieRecommender {

    private MovieCatalog movieCatalog;

    private CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public void prepare(MovieCatalog movieCatalog,
                    CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }

    // ...
}

这两个类如何自动连接实现相同的接口并使用相同的类?

例子:

class Red implements Color
class Blue implements Color

class myMainClass{
    @Autowired 
    private Color color;

    draw(){
        color.design(); 
    } 
}

将调用哪个设计方法?我如何确保红色类的设计方法将被调用,而不是蓝色?


是的,您可以配置Spring servlet上下文xml文件来定义bean(即类),这样它就可以为您自动注入。但是,请注意,要启动并运行Spring,您必须进行其他配置,做到这一点的最佳方法是从头开始学习教程。

一旦你配置好了Spring,你就可以在你的Spring servlet上下文xml文件中执行下面的操作,例如上面的例子1(请替换包名com。如果这是一个第三方类,那么确保适当的jar文件在类路径中):

<beans:bean id="movieFinder" class="com.movies.MovieFinder" />

或者如果MovieFinder类有一个带有原始值的构造函数,那么你可以这样做,

<beans:bean id="movieFinder" class="com.movies.MovieFinder" >
    <beans:constructor-arg value="100" />
</beans:bean>

或者如果MovieFinder类有一个构造函数期望另一个类,那么你可以这样做,

<beans:bean id="movieFinder" class="com.movies.MovieFinder" >
    <beans:constructor-arg ref="otherBeanRef" />
</beans:bean>

...其中'otherBeanRef'是另一个bean,它具有对预期类的引用。


博士TL;

@Autowired注释使您不必自己在XML文件(或任何其他方式)中进行连接,它只是为您找到需要在哪里注入的内容并为您完成该工作。

完整的解释

@Autowired注释允许您跳过要注入内容的其他配置,并为您自行完成。假设你的包是com.mycompany.movies,你必须把这个标签放在你的XML(应用程序上下文文件)中:

<context:component-scan base-package="com.mycompany.movies" />

This tag will do an auto-scanning. Assuming each class that has to become a bean is annotated with a correct annotation like @Component (for simple bean) or @Controller (for a servlet control) or @Repository (for DAO classes) and these classes are somewhere under the package com.mycompany.movies, Spring will find all of these and create a bean for each one. This is done in 2 scans of the classes - the first time it just searches for classes that need to become a bean and maps the injections it needs to be doing, and on the second scan it injects the beans. Of course, you can define your beans in the more traditional XML file or with an @Configuration class (or any combination of the three).

The @Autowired annotation tells Spring where an injection needs to occur. If you put it on a method setMovieFinder it understands (by the prefix set + the @Autowired annotation) that a bean needs to be injected. In the second scan, Spring searches for a bean of type MovieFinder, and if it finds such bean, it injects it to this method. If it finds two such beans you will get an Exception. To avoid the Exception, you can use the @Qualifier annotation and tell it which of the two beans to inject in the following manner:

@Qualifier("redBean")
class Red implements Color {
   // Class code here
}

@Qualifier("blueBean")
class Blue implements Color {
   // Class code here
}

或者如果你更喜欢在XML中声明bean,它看起来像这样:

<bean id="redBean" class="com.mycompany.movies.Red"/>

<bean id="blueBean" class="com.mycompany.movies.Blue"/>

在@Autowired声明中,你还需要添加@Qualifier来告诉你要注入哪一个颜色bean:

@Autowired
@Qualifier("redBean")
public void setColor(Color color) {
  this.color = color;
}

如果你不想使用两个注释(@Autowired和@Qualifier),你可以使用@Resource来组合这两个:

@Resource(name="redBean")
public void setColor(Color color) {
  this.color = color;
}

@Resource(您可以在这个答案的第一个注释中阅读有关它的一些额外数据)使您不必使用两个注释,而是只使用一个注释。

我再加两点评论:

好的做法是使用@Inject而不是@Autowired,因为它不是spring特定的,而是JSR-330标准的一部分。 另一个好的实践是将@Inject / @Autowired放在构造函数上而不是方法上。如果将其放在构造函数上,则可以验证注入的bean不是空的,并且在尝试启动应用程序时快速失败,并在需要实际使用bean时避免出现NullPointerException。

更新:为了完成图片,我创建了一个关于@Configuration类的新问题。


这个例子中没有说“类实现了相同的接口”。MovieCatalog是一种类型,CustomerPreferenceDao是另一种类型。春天很容易就能把它们区分开来。

2.在春天。在x中,bean的连接主要通过bean id或名称进行。Spring 3仍然支持这一点。X,但通常情况下,您将拥有一个具有特定类型的bean实例—大多数服务是单例的。为它们命名是很乏味的。所以Spring开始支持“按类型自动装配”。

这些例子展示了可以用来将bean注入字段、方法和构造函数的各种方法。

XML已经包含了Spring需要的所有信息,因为您必须在每个bean中指定完全限定的类名。不过,你需要小心使用接口:

自动装配将失败:

 @Autowired
 public void prepare( Interface1 bean1, Interface1 bean2 ) { ... }

由于Java没有在字节码中保留参数名,Spring无法再区分这两个bean。修复方法是使用@Qualifier:

 @Autowired
 public void prepare( @Qualifier("bean1") Interface1 bean1,
     @Qualifier("bean2")  Interface1 bean2 ) { ... }