我正在阅读 spring 3.0.x 参考文档以了解 Spring Autowired 注释:
我无法理解以下示例。我们是否需要在 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();
}
}
将调用哪种设计方法?如何确保调用 Red 类的设计方法而不是 Blue?
TL;博士
@Autowired
注释让您无需自己在 XML 文件中进行连接(或任何其他方式),只需为您找到需要注入的内容并为您执行此操作。
完整解释
@Autowired
注释允许您跳过其他地方的注入内容配置并为您完成。假设您的包是 com.mycompany.movies
,您必须将此标记放在您的 XML(应用程序上下文文件)中:
<context:component-scan base-package="com.mycompany.movies" />
此标签将执行自动扫描。假设每个必须成为 bean 的类都使用正确的注释进行注释,例如 @Component
(对于简单 bean)或 @Controller
(对于 servlet 控件)或 @Repository
(对于 DAO
类),并且这些类在某处在包 com.mycompany.movies
下,Spring 将找到所有这些并为每个创建一个 bean。这是在对类的 2 次扫描中完成的——第一次它只是搜索需要成为 bean 的类并映射它需要进行的注入,然后在第二次扫描中注入 bean。当然,您可以在更传统的 XML 文件中或使用 @Configuration
类(或三者的任意组合)来定义您的 bean。
@Autowired
注释告诉 Spring 需要在哪里进行注入。如果将它放在方法 setMovieFinder
上,它会(通过前缀 set
+ @Autowired
注释)理解需要注入 bean。在第二次扫描中,Spring 搜索类型为 MovieFinder
的 bean,如果找到此类 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
(您可以在此答案的第一条评论中阅读有关它的一些额外数据)使您无需使用两个注释,而是只使用一个。
我将再添加两条评论:
好的做法是使用 @Inject 而不是 @Autowired,因为它不是 Spring 特定的并且是 JSR-330 标准的一部分。另一个好的做法是将 @Inject / @Autowired 放在构造函数而不是方法上。如果将它放在构造函数上,则可以验证注入的 bean 不为空,并且在尝试启动应用程序时快速失败,并在需要实际使用 bean 时避免 NullPointerException。
更新:为了完成图片,我创建了一个关于 @Configuration
类的new question。
示例中没有说明“实现相同接口的类”。 MovieCatalog
是一种类型,而 CustomerPreferenceDao
是另一种类型。春天可以很容易地把它们区分开来。
在 Spring 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 ) { ... }
prepare
,将使用哪些参数来调用这个函数?
@Autowired
字段时发生。然后 Spring 将看到需要参数,并将使用与字段注入相同的规则来查找参数。
是的,您可以配置 Spring servlet 上下文 xml 文件来定义您的 bean(即类),以便它可以为您进行自动注入。但是,请注意,您必须进行其他配置才能启动并运行 Spring,而最好的方法是按照教程进行操作。
配置好 Spring 后,您可以在 Spring servlet 上下文 xml 文件中执行以下操作,以使上面的示例 1 起作用(请将 com.movies 的包名称替换为真正的包名称,如果这是第 3 方类,然后确保适当的 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。
@Autowired
的整个想法
不定期副业成功案例分享
MovieFinder
是一个接口,并且我们有一个用于MovieFinderImpl
(bean id = movieFinder) 的 bean,那么 Spring 将按类型或名称自动注入它?@Qualifier
。如果你这样做 - 按名称,如果不是 - 按类型。仅当您的上下文中只有一个MovieFinder
类型的 bean 时,按类型才会起作用。超过 1 会导致异常。@Autowired
注释如何在 示例 2 中的prepare
方法上工作。它正在初始化MovieRecommender
,但从技术上讲,它是 NOT 设置器。@Autowired
也适用于构造函数。它找到所需的依赖项并将它们注入构造函数。