Spring装配bean

Spring装配bean

在Spring框架中,Spring容器负责创建项目中bean并通过DI(依赖注入)的方式来进行装配。

Spring提供了三种装配方式

  1. 在java中进行显式装配
  2. 在XML中进行显式装配
  3. 通过Spring的组件扫描和自动装配技术进行隐式装配

为了解释bean的装配,我们假设一个场景:
CD(compact disc)和CD播放器(CDPlayer),CD需要放入CD播放器中才可以进行播放。

为了描述当前这个场景,我们先定义一个CD接口,定义接口的目的是达到播放器和CD唱片的解耦,这样CD播放器就可以播放任意实现了该接口的具体实现类

public interface CompactDisc {
  void play();
}

接着我们根据该接口实现一个具体类

package soundsystem;

public class SgtPeppers implements CompactDisc {

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

}

同样的我们也设计一个播放器接口MediaPlayer

package soundsystem;

public interface MediaPlayer {
    void play();
}

实现一个MediaPlayer的具体类CDPlayer

package soundsystem;

public class CDPlayer implements MediaPlayer {
  private CompactDisc cd;

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

  public void play() {
    cd.play();
  }
}

通过自动装配技术隐式装配bean

Spring通过两个技术实现自动化装配
组件扫描:Spring会自动扫描并实例化具有特定注解的bean
自动装配:Spring会自动满足bean之间的依赖

要让Spring发现bean的话,我们需要使用到@Component注解;
我们为SgtPeppers和CDPlayer加入该注解

@Component
public class SgtPeppers implements CompactDisc {
	......
}
@Component
public class CDPlayer implements MediaPlayer {
	......
}

@Component注解表明该类会作为组件类,并告知Spring要为这个类创建bean。
你也可以使用@Named注解代替@Component,@Named注解来源于Java依赖注入规范

由于组件扫描默认是不开启的,我们需要显式配置一下

package soundsystem;

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

@Configuration
@ComponentScan
public class CDPlayerConfig { 
}

@Configuration注解表明该类为一个java配置类,(java显示装配时我们再进行介绍);
@ComponentScan注解开启Spring的组件扫描,当没有加其他配置时Spring会扫描和配置的同一个包下的组件。

我们也可以@ComponentScan指定扫描的包名
@ComponentScan(“soundsystem”)
指定扫描soundsystem包下的bean
@ComponentScan(basePackages=“soundsystem”)
或者通过basePackages属性指定
@ComponentScan(basePackages={“soundsystem”, “soundsystem.entity”})
basePackages属性支持指定多个包路径,只需要传入一个数组即可

现在Spring就可以帮我们发现bean并实例化,存放到Spring容器中了

接着我们来完成自动化装配的另一部分自动装配(或称为自动注入)
最开始我们说CD是需要放入CD播放器里才能进行播放,该场景就是我们的自动装配的应用场景了
该场景在CDPlayer的构造器方法中可以体现,我们在构造器方法上使用@Autowired注解

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

加入@Autowired注解后,Spring就会在创建CDPlayer bean时,传入一个CompactDisc的bean给该构造器,从而实例化得到一个CDPlayer bean,存放到Spring容器中

@Autowired注解不光可以使用在构造器方法中,实际上他可以使用在任何方法上,不过除了构造器方法,常用在setter方法中,如下

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

这种写法也可以使得Spring自动注入CompactDisc bean实例化CDPlayer
我们还可以直接在变量上加入@Autowired

@Autowired
private CompactDisc cd;

三种写法都可以得到一个完整的CDPlayer bean,你也可以使用@Inject注解代替@Autowired,@Inject 注解来源于Java依赖注入规范

但是如果Spring找不到一个CompactDisc类型的bean时,Spring会应用上下文创建的时候抛出一个异常,我们可以将@Autowired的required属性设置为false,异常就不会弹出

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

以上例子是在setter上设置@Autowired的required属性,同样在其他方法和变量也是适用的;Spring就不会为这个bean装配CompactDisc bean,当你使用getter获取CompactDisc对象将得到null;
设置required属性虽然可以避免Spring弹出异常,但是需要特别注意的是你需要确保你的类中一个无参构造方法,Spring才可以通过该方法实例化bean,如果没有无参构造方法,Spring同样会弹出异常;
required设置false的方式其实很少使用,一般写了@Autowired注解就是希望有一个bean注入

现在我们就完成了Spring对bean自动化装配,我们对CDPlayer的play方法进行测试

package soundsystem;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.contrib.java.lang.system.SystemOutRule;
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.*;

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

    @Rule
    public final SystemOutRule systemOutRule = new SystemOutRule().enableLog();
    
    @Autowired
    private MediaPlayer player;

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

如果找不到SystemOutRule类,可以加入以下依赖

<dependency>
    <groupId>com.github.stefanbirkner</groupId>
    <artifactId>system-rules</artifactId>
    <version>1.19.0</version>
</dependency>

还有一个小知识,不同系统下的println的“换行”的字符区别
Unix:LF 即"\n";
Windows:CRLF 即"\r\n";
Mac:CR 即"\r"。

在java中进行显式装配

我们直接来看创建CompactDisc bean的java配置的例子

package soundsystem;

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

@Configuration
public class CDPlayerConfig {
    @Bean
    public CompactDisc sgtPeppers(){
        return new SgtPeppers();
    }
}

首先我们需要先创建一个JavaConfig类,通过给java类添加@Configuration注解,即可表明该类为配置类,Spring根据该类帮我们完成相关的配置
再来我们通过@Bean注解与编写一个返回类型为CompactDisc的方法声明一个bean,我们就完成了显式声明了一个bean创建,Spring会帮我们把这个bean放入Spring容器中,相当于在自动化装配中使用@Component注解声明bean

看了简单例子,接下来我们来声明一个MediaPlayer类型的bean,也就是CDPlayer
首先

@Bean
public MediaPlayer cdPlayer(CompactDisc cd){
    return new CDPlayer(cd);
}

我们通过传入CompactDisc类型的参数,new了一个CDPlayer类返回,这样子Spring会自动帮我们寻找CompactDisc类型的bean传入方法帮我们构建bean,只有点类似@Autowired注解的作用,当然我们已经写了sgtPeppers方法来声明CompactDisc bean,你也可以通过调用它new一个CDPlayer

@Bean
public MediaPlayer cdPlayer(){
    return new CDPlayer(sgtPeppers());
}

但是还是推荐交给Spring来自动寻找bean来为我们构建,因为当你要换一个CompactDisc实现类时就不需要再修改它了
在使用java显示配置bean时,你可以使用java实现很多其他功能,比如存在接口类存在多个实现类时,你可以随机一个实现类来声明bean

在XML中进行显式装配

我们先要编写xml配置规范

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

你可以理解为java配置类中的@Configuration注解,我们需要在beans里编写我们的配置;
同样我们先声明一个CD bean

<bean id="cd" class="soundsystem.SgtPeppers"/>

其中id是我们给该bean添加的名字,我们可以通过id在xml的其他地方引用它,class为我们的具体的实现类的包路径;

我们来装配一个CDPlayer bean,由于我们CDPlayer类中有一个带CompactDisc类型参数的构造器方法,我们可以通过他来注入bean

<bean id="cdPlayer" class="soundsystem.CDPlayer">
    <constructor-arg ref="cd"/>
</bean>

我们使用元素来构建bean,使用ref属性来引用bean,它通过id来指定bean;
除外元素的value还可以注入一些具体值,如字符串等
你可以通过c-命名空间来简化xml配置,但是个人感觉差别不大,以及如今xml在工程中的代码量并不是特别多,就不介绍了

总结

Spring支持同时使用三种配置方式,推荐方式是:自动化装配>Java配置>XML配置;
尽管自动化隐式装配很不错,但是有时候我们不得不显式配置,例如一些当你引入一些第三方包时,你没法在源代码,中加入Spring注解,那么就需要显式配置了

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值