了解Spring @Autowired用法

本文翻译自:Understanding Spring @Autowired usage

I am reading the spring 3.0.x reference documentation to understand Spring Autowired annotation: 我正在阅读spring 3.0.x参考文档以了解Spring Autowired注释:

3.9.2 @Autowired and @Inject 3.9.2 @Autowired和@Inject

I am not able to understand the below examples. 我无法理解下面的例子。 Do we need to do something in the XML for it to work? 我们是否需要在XML中执行某些操作才能使用它?

EXAMPLE 1 例1

public class SimpleMovieLister {

    private MovieFinder movieFinder;

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

    // ...
}

EXAMPLE 2 例2

public class MovieRecommender {

    private MovieCatalog movieCatalog;

    private CustomerPreferenceDao customerPreferenceDao;

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

    // ...
}

How can the two classes be autowired implementing the same interface and using the same class? 如何通过自动装配两个类来实现相同的接口并使用相同的类?

Example: 例:

class Red implements Color
class Blue implements Color

class myMainClass{
    @Autowired 
    private Color color;

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

Which design method will be called? 将调用哪种设计方法? How do I make sure the design method of Red class will be called and not Blue? 如何确保调用Red类的设计方法而不是Blue?


#1楼

参考:https://stackoom.com/question/1jsES/了解Spring-Autowired用法


#2楼

Yes, you can configure the Spring servlet context xml file to define your beans (ie, classes), so that it can do the automatic injection for you. 是的,您可以配置Spring servlet context xml文件来定义bean(即类),以便它可以为您执行自动注入。 However, do note, that you have to do other configurations to have Spring up and running and the best way to do that, is to follow a tutorial ground up. 但是,请注意,您必须执行其他配置以使Spring正常运行,并且最好的方法是遵循教程。

Once you have your Spring configured probably, you can do the following in your Spring servlet context xml file for Example 1 above to work (please replace the package name of com.movies to what the true package name is and if this is a 3rd party class, then be sure that the appropriate jar file is on the classpath) : 一旦你可能配置了Spring,你可以在上面的例1的Spring servlet context xml文件中执行以下操作(请将com.movi​​es的包名替换为真正的包名,如果这是第三方class,然后确保相应的jar文件在classpath上):

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

or if the MovieFinder class has a constructor with a primitive value, then you could something like this, 或者如果MovieFinder类有一个具有原始值的构造函数,那么你可以这样,

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

or if the MovieFinder class has a constructor expecting another class, then you could do something like this, 或者如果MovieFinder类有一个构造函数期望另一个类,那么你可以做这样的事情,

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

...where ' otherBeanRef ' is another bean that has a reference to the expected class. ...其中' otherBeanRef '是另一个具有对期望类的引用的bean。


#3楼

TL;DR TL; DR

The @Autowired annotation spares you the need to do the wiring by yourself in the XML file (or any other way) and just finds for you what needs to be injected where, and does that for you. @Autowired注释使您无需在XML文件(或任何其他方式)中自行进行连接,只需找到需要注入的位置,并为您执行此操作。

Full explanation 完整的解释

The @Autowired annotation allows you to skip configurations elsewhere of what to inject and just does it for you. @Autowired注释允许您跳过其他注入内容的配置,并为您完成。 Assuming your package is com.mycompany.movies you have to put this tag in your XML (application context file): 假设您的包是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. 假设每个必须成为bean的类都使用正确的注释进行注释,例如@Component (对于简单bean)或@Controller (对于servlet控件)或@Repository (对于DAO类),这些类位于包com.mycompany.movies之下com.mycompany.movies ,Spring将找到所有这些并为每个创建一个bean。 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. 这是在对类的2次扫描中完成的 - 第一次只搜索需要成为bean的类并映射它需要进行的注入,并在第二次扫描时注入bean。 Of course, you can define your beans in the more traditional XML file or with a @Configuration class (or any combination of the three). 当然,您可以在更传统的XML文件中或使用@Configuration类(或三者的任意组合)定义bean。

The @Autowired annotation tells Spring where an injection needs to occur. @Autowired注释告诉Spring需要注入的位置。 If you put it on a method setMovieFinder it understands (by the prefix set + the @Autowired annotation) that a bean needs to be injected. 如果你把它放在方法setMovieFinder它理解(通过前缀set + @Autowired注释)需要注入一个bean。 In the second scan, Spring searches for a bean of type MovieFinder , and if it finds such bean, it injects it to this method. 在第二次扫描中,Spring搜索MovieFinder类型的bean,如果找到这样的bean,它会将它注入此方法。 If it finds two such beans you will get an Exception . 如果它找到两个这样的bean,你将得到一个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: 为了避免Exception ,您可以使用@Qualifier注释并告诉它以下列方式注入两个bean中的哪一个:

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

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

Or if you prefer to declare the beans in your XML, it would look something like this: 或者如果您更喜欢在XML中声明bean,它看起来像这样:

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

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

In the @Autowired declaration, you need to also add the @Qualifier to tell which of the two color beans to inject: @Autowired声明中,您还需要添加@Qualifier来指示要注入的两个颜色bean中的哪一个:

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

If you don't want to use two annotations (the @Autowired and @Qualifier ) you can use @Resource to combine these two: 如果您不想使用两个注释( @Autowired@Qualifier ),您可以使用@Resource来组合这两个:

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

The @Resource (you can read some extra data about it in the first comment on this answer) spares you the use of two annotations and instead you only use one. @Resource (您可以在此答案的第一条评论中阅读有关它的一些额外数据),可以避免使用两个注释,而只使用一个注释。

I'll just add two more comments: 我将再添加两条评论:

  1. Good practice would be to use @Inject instead of @Autowired because it is not Spring-specific and is part of the JSR-330 standard . 好的做法是使用@Inject而不是@Autowired因为它不是特定于Spring的,而且是JSR-330标准的一部分
  2. Another good practice would be to put the @Inject / @Autowired on a constructor instead of a method. 另一个好的做法是将@Inject / @Autowired放在构造函数而不是方法上。 If you put it on a constructor, you can validate that the injected beans are not null and fail fast when you try to start the application and avoid a NullPointerException when you need to actually use the bean. 如果将它放在构造函数上,则可以验证注入的bean不是null并且在尝试启动应用程序时快速失败并在需要实际使用bean时避免NullPointerException

Update : To complete the picture, I created a new question about the @Configuration class. 更新 :为了完成图片,我创建了一个关于@Configuration类的新问题


#4楼

Nothing in the example says that the "classes implementing the same interface". 示例中没有任何内容表示“实现相同接口的类”。 MovieCatalog is a type and CustomerPreferenceDao is another type. MovieCatalog是一种类型, CustomerPreferenceDao是另一种类型。 Spring can easily tell them apart. Spring很容易将它们分开。

In Spring 2.x, wiring of beans mostly happened via bean IDs or names. 在Spring 2.x中,bean的连线主要通过bean ID或名称进行。 This is still supported by Spring 3.x but often, you will have one instance of a bean with a certain type - most services are singletons. Spring 3.x仍然支持这一点,但通常,您将拥有一个具有特定类型的bean实例 - 大多数服务都是单例。 Creating names for those is tedious. 为这些创建名称是乏味的。 So Spring started to support "autowire by type". 所以Spring开始支持“按类型自动装配”。

What the examples show is various ways that you can use to inject beans into fields, methods and constructors. 示例显示了可用于将bean注入字段,方法和构造函数的各种方法。

The XML already contains all the information that Spring needs since you have to specify the fully qualified class name in each bean. XML已包含Spring需要的所有信息,因为您必须在每个bean中指定完全限定的类名。 You need to be a bit careful with interfaces, though: 但是你需要对接口有点小心:

This autowiring will fail: 此自动装配将失败:

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

Since Java doesn't keep the parameter names in the byte code, Spring can't distinguish between the two beans anymore. 由于Java没有在字节代码中保留参数名称,因此Spring无法再区分这两个bean。 The fix is to use @Qualifier : 修复是使用@Qualifier

 @Autowired
 public void prepare( @Qualifier("bean1") Interface1 bean1,
     @Qualifier("bean2")  Interface1 bean2 ) { ... }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值