Spring–基于注解的容器配置介绍
一、Spring IoC容器简介
1.前言
在JavaEE领域,Spring是当之无愧的王者,它简化了Java应用程序企业级开发的工作,提供了在企业环境中使用Java语言所需的一切。很多初学者学习Spring都是通过网课,整个学习过程十分零碎,学到的也只有单纯的简单应用,而对Spring的设计原则、实现原理都不甚了解,导致的最直接的后果就是:学习过的东西很快就会遗忘,这次解决了程序bug却没搞懂原因,继而下次又会重复碰到类似的bug。
2.什么是IoC?
IoC(Inversion of Control ,控制反转)也称为依赖注入(Dependency Injection)。 在此过程中,对象仅通过
-
构造函数参数
-
工厂方法的参数
-
在构造函数、工厂方法返回对象实例后,在对象实例上设置属性
来定义对象的依赖项 , Spring IoC容器在创建bean时,会自动注入这些依赖项。
举个栗子,在没有引入IOC容器之前,如果对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B,而无论是创建还是使用对象B,控制权都在自己手上。 在引入IOC容器之后,这种情形就完全改变了,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。 通过前后的对比,我们不难看出来:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。
3.IoC容器配置的几种方式
- 基于注解的容器配置(Annotation-based Container Configuration)
- 基于Java的容器配置(Java-based Container Configuration)
- …
二、基于注解的容器配置
1.XML配置与注解配置
在配置Spring时,注释是否比XML更好?Spring文档叙述翻译如下:
基于注释的配置的引入提出了一个问题,即这种方法是否比XML“更好”。简短的答案是“看情况”。长的答案是每种方法都有其优缺点,通常,由开发人员决定哪种策略更适合他们。由于定义方式的不同,注释在声明中提供了很多上下文,从而使配置更短,更简洁。但是,XML擅长连接组件而不接触其源代码或重新编译源代码。一些开发人员更喜欢将配置项放置在靠近源代码的位置,而另一些开发人员则认为带注解的类不再是POJO,而且,该配置变得分散且难以控制。
无论选择如何,Spring都可以容纳两种样式,甚至可以将它们混合在一起。值得指出的是,通过Spring的JavaConfig(Java配置)选项,Spring允许以非侵入方式使用注解,无需接触目标组件的源代码。
另外需要注意的是,注解注入在XML注入之前执行。因此,如果一个属性同时采用了XML配置和注解配置,注解配置将会被XML配置所覆盖。
2.注解配置简介
基于注解的配置提供了XML配置的替代方法,该配置依赖字节码元数据( bytecode metadata )来连接组件,而不是尖括号声明。通过使用相关类,方法或字段声明上的注解,开发人员无需使用XML来描述bean的配置,而是将配置移入组件类本身。
3.用于依赖注入的各种注解
1.@Required
@Required
注解适用于bean属性的Setter方法,如以下示例所示:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Required
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
在此注解下,程序在注入配置时,需要通过bean定义中的显式属性值或通过自动装配来填充相关的bean属性。 如果没有填充相关的bean属性,则容器将引发异常,这种急切的显式失败,可以避免程序运行后再出现空指针异常。
从Spring Framework 5.1版本开始,@Required注解已正式弃用,转而使用构造函数注入进行必需的设置。
2.@Autowired
-
用在构造方法上
public class MovieRecommender { private final CustomerPreferenceDao customerPreferenceDao; @Autowired public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) { this.customerPreferenceDao = customerPreferenceDao; } // ... }
从Spring Framework 4.3版本开始,如果目标bean仅有一个构造函数,则不再需要在构造函数上使用@Autowired批注。 但是,如果目标bean有多个构造函数,则必须至少使用
@Autowired
注释其中一个,以指示容器使用哪个构造函数进行注入。 -
用在Setter方法上
public class SimpleMovieLister { private MovieFinder movieFinder; @Autowired public void setMovieFinder(MovieFinder movieFinder) {