了解Spring @Autowired用法

New*_*ies 295 java spring autowired spring-3

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

    // ...
}
Run Code Online (Sandbox Code Playgroud)

例2

public class MovieRecommender {

    private MovieCatalog movieCatalog;

    private CustomerPreferenceDao customerPreferenceDao;

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

    // ...
}
Run Code Online (Sandbox Code Playgroud)

如何通过自动装配两个类来实现相同的接口并使用相同的类?

例:

class Red implements Color
class Blue implements Color

class myMainClass{
    @Autowired 
    private Color color;

    draw(){
        color.design(); 
    } 
}
Run Code Online (Sandbox Code Playgroud)

将调用哪种设计方法?如何确保调用Red类的设计方法而不是Blue?

Avi*_*Avi 531

TL; DR

@Autowired注释使您无需在XML文件(或任何其他方式)中自行进行连接,只需找到需要注入的位置,并为您执行此操作.

完整的解释

@Autowired注释允许你对什么注入其他地方跳过配置,只是它给你的.假设您的包是com.mycompany.movies必须将此标记放在XML(应用程序上下文文件)中:

<context:component-scan base-package="com.mycompany.movies" />
Run Code Online (Sandbox Code Playgroud)

此标记将执行自动扫描.假设每个必须成为bean的类都使用正确的注释进行注释,例如@Component(对于简单的bean)或@Controller(对于servlet控件)或@Repository(对于DAO类),并且这些类在包的下面com.mycompany.movies,Spring将找到所有这些并创建每个人都有一个豆子.这是在对类的2次扫描中完成的 - 第一次只搜索需要成为bean的类并映射它需要进行的注入,并在第二次扫描时注入bean.当然,您可以在更传统的XML文件中或使用@Configuration类(或三者的任意组合)定义bean .

@Autowired注解告诉Spring去哪里注射需要发生.如果你把它放在一个方法上,setMovieFinder它可以理解(通过前缀set+ @Autowired注释)需要注入一个bean.在第二次扫描中,Spring搜索类型的bean MovieFinder,如果找到这样的bean,它会将它注入此方法.如果它找到两个这样的豆,你会得到一个Exception.为避免这种情况Exception,您可以使用@Qualifier注释并以下列方式告诉它注入两个bean中的哪一个:

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

@Qualifier("blueBean")
class Blue implements Color {
   // Class code here
}
Run Code Online (Sandbox Code Playgroud)

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

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

<bean id="blueBean" class="com.mycompany.movies.Blue"/>
Run Code Online (Sandbox Code Playgroud)

@Autowired声明中,您还需要添加@Qualifier以告知要注入的两个颜色bean中的哪一个:

@Autowired
@Qualifier("redBean")
public void setColor(Color color) {
  this.color = color;
}
Run Code Online (Sandbox Code Playgroud)

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

@Resource(name="redBean")
public void setColor(Color color) {
  this.color = color;
}
Run Code Online (Sandbox Code Playgroud)

@Resource(你可以在这个答案的第一个评论阅读关于它的一些额外的数据),备件您使用两个注释,而是只使用一个.

我将再添加两条评论:

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

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

  • 只是为了完成你的答案:"@ Resource"是JSR-250标准的一部分,并且除了简单的注入之外还有额外的语义(正如你所说的'@Autowired'来自Spring;而'@Inject'是其中的一部分JSR-330):) (6认同)

Aar*_*lla 19

示例中没有任何内容表示"实现相同接口的类".MovieCatalog是一种类型,CustomerPreferenceDao是另一种类型.Spring很容易将它们分开.

在Spring 2.x中,bean的连线主要通过bean ID或名称进行.Spring 3.x仍然支持这一点,但通常,您将拥有一个具有特定类型的bean实例 - 大多数服务都是单例.为这些创建名称是乏味的.所以Spring开始支持"按类型自动装配".

示例显示了可用于将bean注入字段,方法和构造函数的各种方法.

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

此自动装配将失败:

 @Autowired
 public void prepare( Interface1 bean1, Interface1 bean2 ) { ... }
Run Code Online (Sandbox Code Playgroud)

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

 @Autowired
 public void prepare( @Qualifier("bean1") Interface1 bean1,
     @Qualifier("bean2")  Interface1 bean2 ) { ... }
Run Code Online (Sandbox Code Playgroud)


小智 5

是的,您可以配置Spring servlet context xml文件来定义bean(即类),以便它可以为您执行自动注入.但是,请注意,您必须执行其他配置以使Spring正常运行,并且最好的方法是遵循教程.

一旦你可能配置了Spring,你可以在上面的例1的Spring servlet context xml文件中执行以下操作(请将com.movi​​es的包名替换为真正的包名,如果这是第三方class,然后确保相应的jar文件在classpath上):

<beans:bean id="movieFinder" class="com.movies.MovieFinder" />
Run Code Online (Sandbox Code Playgroud)

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

<beans:bean id="movieFinder" class="com.movies.MovieFinder" >
    <beans:constructor-arg value="100" />
</beans:bean>
Run Code Online (Sandbox Code Playgroud)

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

<beans:bean id="movieFinder" class="com.movies.MovieFinder" >
    <beans:constructor-arg ref="otherBeanRef" />
</beans:bean>
Run Code Online (Sandbox Code Playgroud)

...其中' otherBeanRef '是另一个具有对期望类的引用的bean.

  • 定义XML中的所有接线只是错过了`@Autowired`的整个想法 (4认同)