Spring配置的可选方案(三种配置方式)

2023-05-16

版权声明:本文摘自《Spring实战》第4版,[美] Craig Walls 著,张卫滨 译。

本文仅作为学习与交流使用,如有侵权请留言联系作者。转载请注明出处。

目录

一.自动化装配Bean

  注释:@ComponentScan(设置组件扫描的基础包)

  注释:@Autowired

二.通过Java代码装配bean


Spring配置的可选方案主要有三种:

  • 在xml中进行显式配置;
  • 在java中进行显式配置;
  • 隐式的bean发现机制和自动装配;

一.自动化装配Bean

spring从两个角度来实现自动化装配:

1.组件扫描(component scanning):spring会自动发现应用上下文所创建的bean。

2.自动装配(autowiring):spring自动满足spring之间的依赖。

  组件扫描和自动装配组合在一起就能发挥出强大的威力,能将你的显示配置降低到最少。

 

  例子:CD(compact disc)要插入(注入)到CD播放器中,CD播放器才有用。CD播放器依赖于CD才能完成它的使命。

  在Java中定义CD的概念。定义一个CD的接口CompactDisc。作为接口,它定义了CD播放器对一盘CD所能进行的操作。

package soundsystem;

public interface CompactDisc{
    void play();
}

  定义一个带有@Component注解的CompactDisc的实现类SgtPeppers。(可以有多个实现)

package soundsystem;
import org.springframework.stereotype.Component;

@Component
public class SgtPeppers implements CompactDisc {
    private String title = "Sgt. Peppert's Lonely Hearts Club Band";
    private String artist = "The Beatles";
    public void play() {
        System.out.println("Playing "+ title + " by " + artist);
    }
}

       SgtPeppers的具体内容并不重要。需要注意的是SgtPeppers类上使用了@Component注解,这个简单的注解表明该类会作为组件类,并告知Spring要为这个类创建bean。

       组件扫描默认是不启用的。我们还需要显式配置以下Spring,命令它去寻找带有@Component注解的类,并为其创建bean。下面的配置类完成了这项任务的最简洁配置。

@ComponentScan注解启用了组件扫描。

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

@Configuration
@ComponentScan //默认当前包为基础包
public class CDPlayerConfig {
}

       类CDPlayerConfig 通过Java代码定义了Spring的装配规则。如果没有其他配置的话,@ComponentScan默认会扫描与配置类相同的包。因为CDPlayerConfig类位于soundsystem包中,因此Spring将会扫描这个包及其所有子包,查找带有@Component注解的类。这样就能发现CompactDisc,并且会在Spring中自动为其创建一个bean。

注释:@ComponentScan(设置组件扫描的基础包)

@ComponentScan //默认当前包为基础包
//@ComponentScan("soundsystem") //通过value属性指定基础包
//@ComponentScan(basePackages={"soundsystem"}) //指定基础包
//@ComponentScan(basePackages={"soundsystem", "video"}) //指定多个基础包
public class CDPlayerConfig {}

     在上面的例子中,所设置的基础包是以String类型表示的。虽然这是可以的,但这种方法是类型不安全(not type-safe)的。如果你重构代码的话,那么所指定的基础包可能就会出现错误了。

       除了将包设置为简单的String类型之外,@ComponentScan还提供了另外一种方法,那就是将其指定为包中所包含的类或接口:

@ComponentScan(basePackageClasses={CDPlayer.class,DVDPlayer.class)//这些类所在的包会作为组件扫描的基础包

       你可以考虑在包中创建一个用来进行扫描的空标记接口(marker interface)。通过标记接口的方式,你依然能够保持对重构友好的接口引用,但是可以避免引用任何实际的应用程序代码(在以后的重构中,这些应用代码有可能会从想要扫描的包中移除掉)。

       也可以通过XML来启用组件扫描。使用Spring context命名空间的<context:component-scan>元素。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="soundsystem"/>

</beans>

       通过为bean添加注解实现自动装配。借助Spring的@Autowired注解。

       下面的CDPlayer类,它的构造器上添加了@Autowired注解,表明当Spring创建CDPlayer bean的时候,会通过这个构造器来进行实例化并且会传入一个可以设置给CompactDisc类型的bean。

    通过自动装配,将一个CompactDisc注入到CDPlayer之中

package soundsystem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class CDPlayer implements MedisPlayer {
    
    private CompactDisc cd;

    @Autowired
    public CDPlayer(CompactDisc cd){
        this.cd  = cd;
    }

    public void play(){
        cd.play();
    }
}
package soundsystem;
 
public interface MediaPlayer {
	void play();
}

       @Autowired注解不仅能够用在构造器上,还能用在属性的Setter方法上。比如说,如果CDPlayer有一个setCompactDisc()方法,那么可以采用如下的注解形式进行自动装配:

@Autowired
public void setCompactDisc(CompactDisc cd){
    this.cd = cd;
}

注释:@Autowired

       在Spring初始化bean之后,它会尽可能得去满足bean的依赖。实际上,Setter方法并没有什么特殊之处。@Autowired注解可以用在类的任何方法上。假设CDPlayer类有一个insertDisc()方法,那么@Autowired能够像在setCompactDisc()上那样,发挥完全相同的作用:

@Autowired
public void insertDisc(CompactDisc cd){
    this.cd = cd;
}

        不管是构造器、Setter方法还是其他的方法,Spring都会尝试满足方法参数上所声明的依赖。假如有且只有一个 bean匹配依赖需求的话,那么这个 bean 将会被装配进来。

       如果没有匹配的 bean,那么在应用上下文创建的时候,Spring会抛出一个异常。为了避免异常的出现,你可以将@Autowired 的 required 属性设置为 false: 

@Autowired(required = false)
public void CDPlayer(CompactDisc cd){
    this.cd = cd;
}

       将 required属性设置为 false时,Spring尝试执行自动装配时,如果没有匹配的 bean的话,Spring将会让这个bean处于未装配的状态。但是,把 required属性设置为 false时,你需要谨慎对待。如果在你的代码中没有进行 null检查的话,这个处于未装配状态的属性有可能会出现 NullPointerException。

      如果有多个 bean都能满足依赖关系的话,Spring将会抛出一个异常,表明没有明确指定要选择哪个 bean进行自动装配。

       @Autowired是Spring特有的注解,你也可以考虑将其替换为@Inject。

@Inject
public CDPlayer(CompactDisc cd){
    this.cd = cd;
}

       @Inject注解来源于Java依赖注入规范, 在自动装配中,Spring同时支持@Inject和@Autowired。尽管@Inject和@Autowired之间有着一些细微的差别,但是在大多数场景下,它们都是可以互相替换的。

       我们已经在CDPlayer的构造器中添加了@Autowired注解,Spring将把一个可分配给CompactDisc类型的bean自动注入进来。为了验证这一点,创建CDPlayerTest测试类,使其能够借助CDPlayer bean播放CD:

package soundsystem;

import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.StandardOutputStreamLog;
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;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
	
    @Rule
    public final StandardOutputStreamLog log = new StandardOutputStreamLog ();

    @Autowired
    private MediaPlayer player;
    @Autowired
    private CompactDisc cd;
	
    @Test
    public void cdShouldNotBeNull(){
        assertNotNull(cd);
    }

    @Test
    public void play(){
        player.play();
        assertEquals(
            "Playing Sgt. Pepper's Lonely Hearts Club Band by The Beatles\n",
            log.getLog());
    }
}

       现在,除了注入CompactDisc,我们还将CDPlayer bean注入到测试代码的player成员变量之中(它是更为通用的MediaPlayer类型)。在play()测试方法中,我们可以调用CDPlayer的play()方法,并断言它的行为与你的预期一致。

注意:

       在测试代码中使用System.out.println()是稍微有点棘手的事情。因此,该样例中使用了StandardOutputStreamLog,这是来源于System Rules库的一个JUnit规则,该规则能够基于控制台的输出编写断言。在这里,我们断言SgtPeppers.play()方法的输出被发送到了控制台上。


二.通过Java代码装配bean

 

(持续更新中。。。)

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring配置的可选方案(三种配置方式) 的相关文章

随机推荐

  • 19-29-k8s-基本命令-yaml-kubectl

    19 k8s 基本命令 yaml kubectl xff1a Kubernetes 集群的命令行工具kubectl 1 kubectl 命令格式 xff1a kubectl command type name flags 参数 xff1a
  • linux下安装nginx

    linux下安装nginx 注 xff1a 此处需要先安装vmware xff0c 下载Centos8等工具 xff0c 配置好一个虚拟机 1 下载nginx的linux版本 2 上传至搭建好的linux环境上 3 解压nginx压缩包 4
  • 128-152-spark-核心编程-源码

    128 spark 核心编程 源码 xff08 主要以了解基本原理和流程为主 xff09 xff1a 总体相关 1 环境准备 Yarn 集群 1 Driver Executor 2 组件通信 1 Driver 61 gt Executor
  • 6-zookeeper-hadoop-ha原理简述-fail

    6 zookeeper hadoop ha故障转移机制 xff0c 原理简述 HA概述 xff08 2 X版本架构 xff09 1 xff09 HA xff08 High available xff09 xff0c 即高可用 xff08 7
  • treelistview入门使用

    treelistview入门使用 1 创建窗口程序 2 引入库System Runtime InteropServices APIs dll和System Runtime InteropServices APIs dll 3 工具箱添加控件
  • ps-01

    ps 01 入门 xff1a 来源尚硅谷ps课程 xff0c 兴趣而已 xff0c 仅做记录 内容无实质性操作指导 1 软件安装 百度参考各种连接 xff0c 自己安装 https baiyunju cc 10433 2 基础操作 2 1打
  • Notes of Dense Trajectory

    Dense Trajectories densely sample feature points in each frame track points in the video based on optical flow compute m
  • python解析xml文件(解析、更新、写入)

    Overview 这篇博客内容将包括对XML文件的解析 追加新元素后写入到XML xff0c 以及更新原XML文件中某结点的值 使用的是python的xml dom minidom包 xff0c 详情可见其官方文档 xff1a xml do
  • 统计字符串中出现次数最多的字母及其出现次数C++

    小弱鸡看不太懂别人的代码 xff0c 于是用了结构体的方法 xff0c 将字母及其出现次数打包 xff01 include lt iostream gt include lt string h gt include lt algorithm
  • 安装man中文

    安装 man 中文手册 在使用 mac 或者 linux 的时候 xff0c 需要用到命令 xff0c 而大量的命令含有大量 options xff0c 一般很难记住 xff0c 使用 man 可以查看这些命令的 options xff0c
  • Ubuntu 18.04安装PyCharm社区版

    下载 下载 xff1a 或直接官网下载 链接 xff1a https pan baidu com s 1JLmMqJNBvClLAYuK1rlKrw 提取码 xff1a 41qk 安装 下载完后进入到存储文件的地址执行以下代码 xff0c
  • Android安卓动态获取存储权限,保存文件到外部存储

    添加存储权限 lt 外部存储的写权限 gt lt uses permission android name 61 34 android permission WRITE EXTERNAL STORAGE 34 gt lt 外部存储的读权限
  • 按键消抖详解

    一 按键消抖原理 抖动时间的长短由按键的机械特性决定 xff0c 一般为 5ms xff5e 10ms xff0c 键抖动会引起一次按键被误读多次 解决办法 xff1a 判断按键按下时 xff0c 延时 10 ms 即可 二 软件实现按键消
  • 20 分钟梳理 Spring 全家桶 !

    作 者 xff1a Daisy 授权转自IT技术思维 xff0c 每日精选优质干货 xff0c 欢迎关注 xff01 xff1e xff1e xff1c xff1c Spring框架自诞生以来一直备受开发者青睐 xff0c 有人亲切的称之为
  • Linux添加软件分类(GNOME桌面)

    Linux添加软件分类 xff08 GNOME桌面 xff09 之前安装TIM deepin wine 的时候发现TIM的分类为chat xff0c 而系统默认没有这个分类 xff0c 所以TIM就很自然的被划分到 其他 里边去了 这强迫症
  • gnome扩展推荐

    引言 xff1a gnome在Linux世界里作为一个比较流行的桌面环境 xff0c 默认不是十分美观 xff0c 有些功能也没有 xff0c 这个时候我们就可以选择安装扩展去个性化gnome 下面是我的桌面截图 xff0c 我利用了扩展实
  • SpringBoot + Redis实现布隆过滤器

    一 简述 关于布隆过滤器的详细介绍 xff0c 我在这里就不再赘述一遍了 我们首先知道 xff1a BloomFilter使用长度为m bit的字节数组 xff0c 使用k个hash函数 xff0c 增加一个元素 通过k次hash将元素映射
  • 屏蔽效能预估

    今天完成了屏蔽效能预估部分的程序 由于公式比较多 xff0c 而且就编程本身而言技术含量不高 xff0c 因此不将源代码贴出 xff0c 有需要者可以联系我 程序界面如下 xff1a
  • SSH 命令的11种用法

    使用ssh连接远程主机 最简单的用法只需要指定用户名和主机名参数即可 xff0c 主机名可以是 IP 地址或者域名 ssh user 64 hostname ssh连接到其他端口 SSH 默认连接到目标主机的 22 端口上 xff0c 可以
  • Spring配置的可选方案(三种配置方式)

    版权声明 xff1a 本文摘自 Spring实战 第4版 xff0c 美 Craig Walls 著 xff0c 张卫滨 译 本文仅作为学习与交流使用 xff0c 如有侵权请留言联系作者 转载请注明出处 目录 一 自动化装配Bean 注释