Spring入门(二):自动化装配bean

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

  • 组件扫描(component scanning):Spring会自动发现应用上下文中需要创建的bean。
  • 自动装配(autowiring):Spring会自动满足bean之间的依赖。

为了更形象的解释组件扫描与自动装配,我们举一个音响系统的例子,主要包含以下内容:

  • CD接口
  • CD接口的一个实现类
  • CD播放器

关于CD和CD播放器关系的解释:

如果你不将CD插入(注入)到CD播放器中,那么CD播放器其实是没有太大用处的。所以,可以这样说,

CD播放器依赖于CD才能完成它的使命。

1.创建可被发现的bean

先创建CD接口CompactDisc:

package soundsystem;

public interface CompactDisc {
    void play();
}

然后创建CD接口的一个实现类SgtPeppers:

package soundsystem;

import org.springframework.stereotype.Component;

@Component
public class SgtPeppers implements CompactDisc {

    @Override
    public void play() {
        String title = "Sgt.Pepper's Lonely Hearts Club Band ";
        String artists = "The Beatles";
        System.out.println("Playing " + title + " By " + artists);
    }
}

SgtPeppers类与以往类的区别在于使用了@Component注解。这个注解表明该类会作为组件类,并告知Spring要为这个类创建bean。

创建了bean,那么如何让Spring发现它呢?这时就需要用到组件扫描,不过,在Spring中,组件扫描默认是不启用的。因此我们需要显式配置一下Spring,从而命令它去寻找带有@Component注解的类,并为其创建bean。

创建CDPlayerConfig类:

package soundsystem;

import org.springframework.context.annotation.ComponentScan;

@ComponentScan
public class CDPlayerConfig {
}

这个类与以往类的区别是使用了@ComponentScan注解,这个注解能够Spring中启用组件扫描。

@ComponentScan默认会扫描与配置类相同的包以及这个包下的所有子包,查找带有@Component注解的类。

2.验证组件扫描

为了验证创建的bean能否被Spring发现,我们创建一个简单的JUnit测试,完成此测试需要导入以下两个jar包:

  • hamcrest-core-2.1.jar
  • junit-4.12.jar

导入jar包的方式如下:

导入完成后的项目结构图如下所示:

package soundsystem;

import static org.junit.Assert.*;

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;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {

    @Autowired
    private CompactDisc compactDisc;

    @Test
    public void cdShouldNotBeNull() {
        assertNotNull(compactDisc);
        compactDisc.play();
    }
}

代码简单讲解:

@RunWith(SpringJUnit4ClassRunner.class),会在测试开始的时候自动创建Spring的应用上下文。

@ContextConfiguration(classes = CDPlayerConfig.class)会告诉Spring需要在CDPlayerConfig中加载配置。

字段compactDisc上的@Autowired注解,会将CompactDisc bean(其实是SgtPeppers)注入到测试代码之中。

运行测试方法cdShouldNotBeNull,会发现测试通过,compactDisc不为null:

3.为组件扫描的bean命名

Spring应用上下文中所有的bean都会给定一个ID,默认情况下,Spring会将类名的第一个字母变为小写,作为该bean的ID。

如上面代码中SgtPeppers bean的ID为sgtPeppers。

有以下两种方式来设置bean ID:

方式1:使用@Component设置bean ID

@Component("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc {
    ...
}

方式2:使用@Named设置bean ID

@Named注解不是Spring框架的注解,而是Java 依赖注入规范(Java Dependency Injection)中的注解,因此需要导入jar包:javax.inject-1.jar。

package soundsystem;

import javax.inject.Named;

@Named("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc {
    ...
}

在Spring项目中建议使用@Component注解。

4.设置组件扫描的基础包

按照默认规则 ,@ComponentScan注解会以配置类所在的包作为基础包(base package)来扫描组件。

但有时候,我们会将配置类放在单独的包中,使其与其他的应用代码区分开来。

这种场景下,默认的基础包就满足不了需求。

@ComponentScan注解支持传入指定的基础包,有以下几种场景:

4.1 指定要扫描的基础包(单个)

@ComponentScan("soundsystem")
public class CDPlayerConfig {
}

或者:

@ComponentScan(basePackages = "soundsystem")
public class CDPlayerConfig {
}

4.2 指定要扫描的基础包(多个)

@ComponentScan(basePackages = {"soundsystem", "video"})
public class CDPlayerConfig {
}

4.3 指定要扫描的基础包(类型安全)

@ComponentScan(basePackageClasses = {CDPlayer.class})
public class CDPlayerConfig {
}

如上所示,basePackageClasses也支持指定多个类,指定类所在的包将会作为组件扫描的基础包。

建议使用这种类型安全方式来指定扫描的基础包。

5.通过为bean添加注解实现自动装配

自动装配是让Spring自动满足bean 依赖的一种方法,在满足依赖的过程中,会在Spring应用上下文中寻找匹配某个bean需要的其他bean。

实现自动装配,需要使用Spring的@Autowired注解。

@Autowired一般情况下,有以下3种使用方式:

5.1 使用在构造器上

package soundsystem;

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

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

@Component
public class CDPlayer implements MediaPlayer {

    private CompactDisc compactDisc;

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

    @Override
    public void play() {
        compactDisc.play();
    }
}

5.2 使用在属性的Setter方法上

package soundsystem;

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

@Component
public class CDPlayer implements MediaPlayer {

    private CompactDisc compactDisc;

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

    @Override
    public void play() {
        compactDisc.play();
    }
}

5.3 使用在类的任何方法上

package soundsystem;

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

@Component
public class CDPlayer implements MediaPlayer {

    private CompactDisc compactDisc;

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

    @Override
    public void play() {
        compactDisc.play();
    }
}

不管是构造器、Setter方法还是其他的方法,Spring都会尝试满足方法参数上所声明的依赖。

假如有且只有一个bean匹配依赖需求的话,那么这个bean将会被装配进来。

如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。

可以通过设置require属性为false避免该异常出现:

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

不过建议谨慎使用,避免未找到bean进行匹配,而且代码没有进行null检查而出现NullPointerException。

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

@Autowired注解也可以替换成@Inject注解(来源于Java依赖注入规范),同样可以实现自动装配:

package soundsystem;

import org.springframework.stereotype.Component;
import javax.inject.Inject;

@Component
public class CDPlayer implements MediaPlayer {

    private CompactDisc compactDisc;

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

    ...
}

在Spring项目中建议使用@Inject注解。

6.验证自动装配

修改CDPlayerTest类代码测试自动装配

package soundsystem;

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;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {

    @Rule
    public final StandardOutputStreamLog log = new StandardOutputStreamLog();

    @Autowired
    private MediaPlayer player;

    @Autowired
    private CompactDisc compactDisc;

    @Test
    public void cdShouldNotBeNull() {
        assertNotNull(compactDisc);
        compactDisc.play();
    }

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

因为代码中使用了StandardOutputStreamLog类,因此需要导入jar包:system-rules-1.16.0.jar

运行测试方法play(),输出内容和预期一致,说明字段player已经被MediaPlayer的实现类CDPlayer bean装配,测试通过,如下所示:

7.源码地址

https://github.com/zwwhnly/SpringStudyDemo.git,欢迎大家下载,有问题可以多多交流。

原文地址:https://www.cnblogs.com/zwwhnly/p/10478615.html

时间: 2024-10-08 19:35:03

Spring入门(二):自动化装配bean的相关文章

Spring学习系列(二) 自动化装配Bean

一.Spring装配-自动化装配 @Component和@ComponentScan 通过spring注解(@Component)来表明该类会作为组件类,并告知Spring要为这类创建bean,不过组件扫描默认是不启动的,需要显式的配置Spring,从而命令Spring去寻找带有(@Component)注解的类,并为其创建bean. 1.定义接口 package com.seven.springTest.service; public interface HelloWorldApi { publ

Spring 之自动化装配 bean 尝试

[Spring之自动化装配bean尝试] 1.添加dependencies如下所示(不是每一个都用得到 <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.9.RELEASE</version> </dependency

Spring 实战-第二章-装配Bean

Bean是Spring对象的声明(装配wiring),要使用Spring,必须先装配需要使用的对象,有3种装配的方式 自动化装配Bean 通过Java代码装配 通过XML装配 自动化装配Bean 自动化装配Bean很简单 1.声明接口 package soundsystem; public interface CompactDisc { void play(); } 2.添加注解 package soundsystem; import org.springframework.stereotype

Spring实战3:装配bean的进阶知识

主要内容: Environments and profiles Conditional bean declaration 处理自动装配的歧义 bean的作用域 The Spring Expression Language 在装配bean—依赖注入的本质一文中,我们探讨了Spring的三种管理bean的方式:自动装配.基于JavaConfig.基于XML文件.这篇文字将探讨一些Spring中关于bean的管理的高级知识,这些技能你可能不会每天都用,但是非常重要. 3.1 Environments

Spring之IOC&amp;DI/装配Bean(一)

简介 今天学习Spring的第一天,无非也就是入门基础知识.主要了解IOC和DI部分,要熟练掌握哦~ Spring简介 1. Spring介绍 Spring是一个非常活跃的开源框架:它是一个基于Core来构架多层JavaEE系统的框架,它的主要目地是简化企业开发. Spring以一种非侵入式的方式来管理你的代码,Spring提倡"最少侵入",这也就意味着你可以适当的时候安装或卸载Spring 2. Spring框架的优势 ?方便解耦,简化开发 ?Spring就是一个大工厂,可以将所有对

Spring学习总结之---装配Bean

Spring配置的可选方案 前言:Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系,作为开发人员,你需要告诉Spring容器要创建那些Bean,以哪种方式创建,并且如何将这些bean装配在一起. 1.装配方式可选方案: 1-1:在XML中进行显示配置:在java中进行显示配置:隐式的bean发现机制和自动装配:可以使用互相搭配使用.备注:建议使用自动装配方式. 2.自动化装配:组件扫描(Spring会自动对发现组件类进行扫描并创建上下文bean):自动装配(Spri

Spring基础知识之装配Bean

装配(wiring):创建应用对象之间协作关系的行为.这是依赖注入的本质. Spring配置的可选方案 Spring提供了三种装配机智: 1)在XML中进行显示装配 2)在java中进行显示装配 3)隐式Bean发现机制和自动装配 自动化装配 Spring从两个角度来实现自动化装配: 1)组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean. 2)自动装配(autowiring):Spring自动满足bean之间的依赖. 创建可被发现的bean 案

自动化装配Bean

一.Spring装配-自动化装配 @Component和@ComponentScan 通过spring注解(@Component)来表明该类会作为组件类,并告知Spring要为这类创建bean,不过组件扫描默认是不启动的,需要显式的配置Spring,从而命令Spring去寻找带有(@Component)注解的类,并为其创建bean. 1.定义接口 package com.seven.springTest.service; public interface HelloWorldApi { publ

&lt;Spring实战&gt;2:装配Bean

1 声明Bean 1.1 创建 Spring 配置 Spring 容器提供两种配置 Bean 的方式:xml 配置和基于注解配置. Spring 配置文件: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/