了解Spring @Autowired用法

我正在阅读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(); 
    } 
}

哪种设计方法会被调用? 我如何确保Red类的设计方法被调用而不是蓝色?


@Autowired注释允许您跳过注入内容的其他位置,只是为您做。 假设你的包是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包下的某个位置com.mycompany.movies ,Spring会找到所有这些并为每个bean创建一个bean。 这是在2个类的扫描中完成的 - 它第一次只搜索需要成为bean的类并映射它需要做的注入,而在第二次扫描时它注入了bean。 当然,您可以在更传统的XML文件或@Configuration类(或三者的任意组合)中定义bean。

@Autowired注释告诉Spring需要发生注入。 如果你把它放在setMovieFinder方法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
  • 因此,总结一下: @Autowired注释让您无需自己在XML文件中(或以任何其他方式)进行布线,只需找到需要注入的地方,并为您做到这一点。

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


    示例中没有说“实现相同接口的类”。 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 ) { ... }
    

    是的,您可以配置Spring servlet上下文xml文件来定义您的bean(即类),以便它可以为您自动注入。 但是,请注意,您必须执行其他配置才能使Spring正常运行,并且最好的方法是完成一个教程。

    一旦你的Spring配置好了,你可以在你的Spring servlet上下文xml文件中为上面的例子1执行以下操作(请将com.movi​​es的包名替换为真正的包名,如果这是第三方类,然后确保相应的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。

    链接地址: http://www.djcxy.com/p/22687.html

    上一篇: Understanding Spring @Autowired usage

    下一篇: How to inject Spring Bean for factory method requiring MyClass.class parameter