- IoC(Inversion of Control,控制反转 ):控制权由应用代码中转到了外部容器,控制权的转移,所谓控制反转。
- 依赖注入:依赖注入是控制反转(IOC)的一个层面,用创建对象而只需要描述如何创建它们。
IoC 负责装配 Bean,即创建应用对象之间协作关系,是依赖注入(DI,Dependency injection)的本质。
装配方式优先级:自动装配 > Java 配置文件 > XML 配置文件
1 自动装配
Spring 容器可以自动配置相互协作 beans 之间的关联关系。这意味着 Spring 可以自动配置一个 bean 和其他协作 bean 之间的关系。
Spring 从两个角度来实现自动装配
1.1 组件扫描
Spring 自动发现 ApplicationContext 中所创建的 bean
1)@Component
让 Spring 为类自动创建 bean,默认 ID 是类名称的首字母小写。也可给注解传入指定的参数指定名字。
@Component
@Component("lonelyHeartsClub")
还有 @Repository、@Service、@Controller 等
2)@ComponentScan
开启 Component 扫描,默认设置该目录以及子目录下所有被 @Component 注解修饰的类。也可指定扫描的包。
@ComponentScan("soundsystem")//扫描指定包
@ComponentScan(basePackages = "soundsystem")
@ComponentScan(basePackages = {"soundsystem", "video"})
@ComponentScan(basePackageClasses = {CDPlayer.class, DVDPlayer.class})//扫描指定类所属的包
1.2 自动装配
Spring 自动满足 bean 之间的依赖
@Autowired:声明自动装配,可用在构造器、方法、成员变量上。
只要对应类型的 bean 有且只有一个,则会自动装配。推荐通过构造器注入以避免 NullPointerException 问题。
1)注入到 Java 集合类
@Autowired 可直接将接口的实现 Bean 注入到如下几种类型的集合中
- list:用来注入一系列的值,允许有相同的值。
- set:用来注入一些列的值,不允许有相同的值。
- map:用来注入一组”键-值”对,key 必须为 String。
- props:也可以用来注入一组”键-值”对,这里的键、值都字符串类型。
@Autowired
private List<BeanInterface> list;
@Autowired
private Map<String,Interface> map;
application.properties
table-info.list[0]=list_value1
table-info.list[1]=list_value2
table-info.map.map_key1=map_value1
table-info.map.map_key2=map_value2
table-info.maplist.map_key1[0]=maplist_value1
table-info.maplist.map_key1[1]=maplist_value2
table-info.maplist.map_key2[0]=maplist_value3
TableConfig
@ConfigurationProperties(prefix = "table-info")
public class TableConfig {
private List<String> list;
private Map<String, String> map;
private Map<String, List<String>> maplist;
}
2)允许 null 值
默认要求依赖对象必须存在,如允许 null 值,可设置 @Autowired(required=false)
还有 @Resource 等
3)推荐对构造函数进行注释
由
@Autowired
private EnterpriseDbService service;
改为
private final EnterpriseDbService service;
@Autowired
public EnterpriseDbController(EnterpriseDbService service) {
this.service = service;
}
可以明确成员变量的加载顺序
2 Java 配置文件
想要装配第三方库中的组件时,因为没办法在它的类上添加 @Component 和 @Autowired 注解,不能自动化配置,必须要采用显式装配。
2.1 创建配置类
@Configuration:表明是配置类
2.2 声明 bean
@Bean:声明 bean,需编写方法创建所需类型实例, 注解 @Bean。默认 ID 是方法名,也可通过 name 属性指定名字。
@Bean(name = "lonelyHeartsClub")
public CompactDisc sgtPeppers() {
return new SgtPeppers();
}
2.3 装配 bean
在 JavaConfig 中装配 bean 的最简单方式就是引用创建 bean 的方法。
默认情况下,Spring 中所有的 bean 都是单例模式,Spring 会拦截 @Bean 注解的函数调用,并返回之前创建好的 bean。
@Bean
public CDPlayer cdPlayer() {
return new CDPlayer(sgtPeppers());
}
3 XML 配置文件
维护已有的 XML 配置, 在完成新的 Spring 工作时, 使用自动化配置和 JavaConfig。
创建一个 XML 文件, 并且以
可以同时使用两种方式的依赖注入,最好的选择是使用构造器参数实现强制依赖注入,使用 setter 方法实现可选的依赖关系。
3.1 set 注入
首先容器会触发一个无参构造函数或无参静态工厂方法实例化对象,之后容器调用 bean 中的setter 方法完成 Setter 方法依赖注入。
private OrderServiceImp orderService;
public void setOrderService(OrderServiceImp orderService) {
this.orderService = orderService;
}
Spring 配置 XML 文件:其中配置声明 OrderAction 类存在属性 orderService。程式运行时候,会将已经实例化的 orderService 对象调用 setOrderService 方式注入。
<bean name="orderAction" class="com.pec.action.OrderAction">
<property name="orderService" ref="orderService"></property>
</bean>
<bean name="orderService" class="com.pec.service.imp.OrderServiceImp"></bean>
3.2 构造器注入
构造器依赖注入在容器触发构造器的时候完成,该构造器有一系列的参数,每个参数代表注入的对象。
private OrderServiceImp orderService;
public OrderAction(OrderServiceImp orderService) {
this.orderService = orderService;
}
Spring 配置 XML 文件
<bean name="orderAction" class="com.pec.action.OrderAction">
<constructor-arg ref="orderService"></constructor-arg>
</bean>
<bean name="orderService" class="com.pec.service.imp.OrderServiceImp"></bean>
4 多种配置方法混用
通常的做法是:无论使用 JavaConfig 或者 XML 装配,都要创建一个 root configuration;并且在这个配置文件中开启自动扫描机制
4.1 JavaConfig 中引用
- @Import:导入其他的 JavaConfig
- @ImportResource:导入 XML 配置文件
@Import({CDPlayerConfig.class, CDConfig.class})
@ImportResource("classpath: cd-config.xml")
4.2 XML 配置中引用
<import resource="classpath:/spring/calculate-web.xml"/>
<bean class="soundsystem.CDConfig" />