Spring中bean的三种装配机制之——自动装配

来源:互联网 发布:淘宝网电脑不能登录 编辑:程序博客网 时间:2024/05/09 03:40

基本介绍

  关于各种配置,从来没搞懂过。但是觉得框架发展这么快,而且结构这么宏大,其实现微观上来讲应该从来没有一种标准方式、更没有说是固定的几种。比如Spring专有的@Component、@Autowired注解,大多数情况下都可以被javax.inject包下的@Named和@Inject代替。本博文汇总《Spring 实战 第四版》2.1和2.2内容。
  自动装配是使用spring满足bean依赖的一种方法,满足以来的过程中,spring会在应用上下文中为某个bean寻找其依赖的bean
  Spring中bean有三种装配机制,分别是:
1. 在xml中显示配置;
2. 在java中显示配置;
3. 隐式的bean发现机制和自动装配。
这里我们主要讲第三种:自动化的装配bean。

自动化的装配bean

  Spring的自动装配需要从来能个角度来实现,或者说是两个操作:
    1.组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean;
    2.自动装配(autowiring):spring自动满足bean之间的依赖,也就是我们上篇博文说的IoC/DI;
  组件扫描和自动装配组合发挥巨大威力,使的显示的配置降低到最少

一.bean自动装配的基本方式及测试

  这里以“光碟机”和“cd播放器”为例来介绍自动装配的基本实现方式。假设我们有个光碟接口CompacDisc,其具体实现类为各个明星的专辑,实现如下:

package com.example.springboot.demo.soundsystem;import org.springframework.stereotype.Component;@Component//表明该类会作为组件类,告知spring为这个类创建beanpublic class SgtPeppers implements CompactDisc {    private String title="ye hui mei";    private String artist="zhou jie lun";    @Override    public void play() {        System.out.println("playing "+title+" by "+artist);    }}

  通过@Component告知Spring为SgtPeppers 创建bean是不够的,我们还需要让spring知道去哪里扫描可能带有@Component的类,盲目的全局扫描是不可行的。这里我们使用在配置类中使用@Component注解启用组件扫描,也就是@Configuration+@ComponentScan。简单的一逼,实例如下:

package com.example.springboot.demo.soundsystem;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;/** * @author 杜艮魁 * @date 2017/12/10 */@Configuration@ComponentScanpublic class CDPlayerConfig {}

  在这里@ComponentScan等同于@ComponentScan(“com.example.springboot.demo.soundsystem”)和@ComponentScan(basePackges=“com.example.springboot.demo.soundsystem”),即将基础包设置为配置类所在的包,spring会扫描配置类所在的包及其子包
  除此之外,@Component和@ComponentScan还有诸如配置bean名称、设置基础包路径、设置基础包路经集合、使用类或接口标记基础包所在位置等东西,稍后示例我们在展开讲解。
  以上配置是否生效,我们使用一下示例测试:

package com.example.springboot.demo.soundsystem;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import static org.junit.Assert.*;/** 1. @author 杜艮魁 2. @date 2017/12/10 */@RunWith(SpringJUnit4ClassRunner.class)//告诉Spring在测试的时候创建应用上下文;@ContextConfiguration(classes = CDPlayerConfig.class)//告诉测试程序在CDPlayerConfig类中加载配置public class CDPlayerTest {    @Autowired    private CompactDisc compactDisc;    @Test    public void cdShouldNotBeNull(){        assertNotNull(compactDisc);    }}//输出:Process finished with exit code 0

  之所以输出为“真”是因为:
  1.@RunWith(SpringJUnit4ClassRunner.class)告诉Spring在测试的时候创建应用上下文;
  2.@Configuration和@ComponentScan注解创建应用上下文时扫描到了同包下@Component注解的CompactDisc接口的实现类SgtPeppers,然后spring为其创建bean;
  3.@ContextConfiguration(classes = CDPlayerConfig.class)告诉测试程序在CDPlayerConfig类中加载配置

二.为bean命名

  bean的默认名称为雷米给你的第一个字母小写,即:

@Componentpublic class SgtPeppers implements CompactDisc {...}同@Component("sgtPeppers")//引号内名称可以自定义public class SgtPeppers implements CompactDisc {...}

我们可以自定义名称,一共我们以后方便使用。

三.设置组件扫描的基础包:集合、类/接口标识、同义替换及他们的相关测试

  配置类类名上只有一个@ComponentScan是不够的,当我们想把配置类单独放在一个包里,而bean又不在其子包时,我们需要制定包路径。更甚者bean不在同一个父亲包中是,我们就要使用路径集合来制定扫描的路径。基本实现方式如下:
  1)包路径法:

@ComponentScan("XXXX")@ComponentScan(basePackages={"xx","yy"})

  2)类/接口定位法:当我们重构代码时,包路径可能不在有效,此时我们可以指定一个类或者接口,将这些类/接口所在的包指定为基础包,注意使用basePackageClasses属性。实际使用中我们可以定义“空标记类(marker interface)”,而不一定甚至不应该使用实际的业务类。

@ComponentScan(basePackageClasses={demo.class})
五.为bean添加注解实现自动装配

  在bean中声明对依赖的bean进行自动装配,我们可以借助Spring的@Autowired或者javax.inject包下的@Inject注解。@Autowired可以用在构造参数或者被依赖bean的setter方法上,而且方法名是没有限制的。不管两者哪一个,spring都会尝试满足方法参数所声明的依赖。
  但是如果以来的bean不存在或者我们忘了加@Component注解,spring会在创建应用上下文的时候抛异常。处理方式时为@Autowired属性required设置false,并在代码中检查其是否是null。
  重申:Spring专有的@Component、@Autowired注解,大多数情况下都可以被javax.inject包下的@Named和@Inject代替。

相关项目github地址