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

基本介绍

  关于各类配置,历来没搞懂过。可是以为框架发展这么快,并且结构这么宏大,其实现微观上来说应该历来没有一种标准方式、更没有说是固定的几种。好比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。java

自动化的装配bean

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

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

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

package com.example.springboot.demo.soundsystem;

import org.springframework.stereotype.Component;

@Component//代表该类会做为组件类,告知spring为这个类建立bean
public 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。简单的一逼,实例以下:web

package com.example.springboot.demo.soundsystem;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/** * @author 杜艮魁 * @date 2017/12/10 */

@Configuration
@ComponentScan
public class CDPlayerConfig {
}

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

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类中加载配置springboot

二.为bean命名

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

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

咱们能够自定义名称,一共咱们之后方便使用。框架

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

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

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

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

@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地址