了解Spring @Autowired的用法

我正在阅读春季网站,了解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(); } } 

哪种devise方法会被调用? 我如何确保Red类的devise方法被调用而不是Blue?

@Autowired注释允许你跳过configuration的其他地方,只是为你做。 假设你的包是com.mycompany.movies你必须把这个标签放在你的XML(application context file)中:

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

这个标签会做一个自动扫描。 假设每个必须成为bean的类都使用@Component (对于简单bean)或@Controller (对于servlet控件)或@Repository (对于DAO类)进行注释,而这些类位于com.mycompany.movies ,Spring会find所有这些,并为每个bean创build一个bean。 这是在两个类的扫描中完成的 – 第一次它只search需要成为一个bean的类并映射它需要做的注入,在第二次扫描时注入bean。 当然,您可以在更传统的XML文件或@Configuration类(或这三者的任意组合)中定义bean。

@Autowired注释告诉Spring注入需要发生的地方。 如果你把它放在setMovieFinder方法setMovieFinder它可以理解(通过前缀set + @Autowired注解)一个bean需要被注入。 在第二个扫描中,Springsearch一个types为MovieFinder的bean,如果它find了这个bean,它将它注入到这个方法中。 如果发现两个这样的bean,你将会得到一个Exception 。 为了避免这个Exception ,你可以使用@Qualifier注解,并通过下面的方式告诉它注入两个bean中的哪一个:

 @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 (你可以在这个答案的第一个注释中读到一些关于它的额外的数据)让你使用两个注释,而只使用一个。

我只会再添加两条评论:

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

所以,总结一下: @Autowired注解不需要你自己在XML文件中(或者其他任何方式)进行布线,只需要find需要注入的地方,并且为你做。

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

示例中没有任何内容说“实现相同接口的类”。 MovieCatalog是一个types, CustomerPreferenceDao是另一个types。 spring可以很容易地把它们分开。

在Spring 2.x中,bean的连线主要是通过bean的ID或名字发生的。 Spring 3.x仍然支持这个function,但通常情况下,您将拥有一个具有特定types的bean的实例 – 大多数服务都是单例。 为这些人创build名字是很乏味的。 所以Spring开始支持“autowire type”。

这些示例显示的是可以使用各种方法将bean注入字段,方法和构造函数。

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

这种自动assembly将失败:

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

由于Java不保存字节码中的参数名称,因此Spring无法区分这两个bean。 修正是使用@Qualifier

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

是的,您可以configurationSpring servlet上下文xml文件来定义您的bean(即类),以便它可以为您自动注入。 然而,请注意,你必须做其他的configuration才能使Spring运行起来,而最好的方法是按照教程进行操作。

一旦你的Springconfiguration好了,你可以在Spring servlet上下文xml文件中为上面的例子1做下面的工作(请 com.movi​​es的包名replace成真正的包名,如果这是第三方类,然后确保相应的jar文件在类path中):

 <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。

@Autowired

让Spring使用@Autowired注释将其他bean自动连线到您的类中。

 @Service public class CompanyServiceImpl implements CompanyService { @Autowired private CompanyDAO companyDAO; ... } 

Spring Annotation提示Spring bean可以按名称或types进行连接。 @Autowire默认是一个types驱动注入。 可以使用@Qualifier spring注释来进一步微调自动assembly。 @Resource(javax.annotation.Resource)注释可以用于按名称连线。 本身被定义为集合或映射types的Bean不能通过@Autowired注入,因为types匹配不适用于它们。 对这样的bean使用@Resource,通过唯一名称引用特定的集合或映射bean