Spring构造函数注入方式详解

发布时间:2020-08-28 18:36:11 作者:微然月明
来源:网络 阅读:2788

  本文讲解spirng三种注入方式(构造函数注入,setter注入,注解注入)中的构造函数注入。

  所有例子,都是以注解的方式注册bean。

  关于构造函数方式注入,spring官网的说明地址为:Spring官网之构造函数注入

1. 构造函数只有一个参数且类型为单个实现类

单参数且单实现类这是一种最简单的以构造函数的注入方式注入依赖,只要在构造函数中添加所依赖类型的参数即可,spring会匹配对应类型的bean进行注入,由于只有一个对应类型的实现类,因此能准确地找到bean进行注入。

我们看以下例子:

public interface GoPlay {

    public void havePlay();
}
import org.springframework.stereotype.Component;

@Component
public class GoPlayImpl implements GoPlay {
    @Override
    public void havePlay() {
        System.out.println("\n\nsingle play\n\n");
    }
}
import org.springframework.stereotype.Component;

@Component
public class PlayController {
    private GoPlay goPlay;

    public PlayController(GoPlay goPlay) {
        this.goPlay = goPlay;
    }

    public void play(){
        goPlay.havePlay();
    }
}
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

@RunWith(SpringRunner.class)
@SpringBootTest
public class PlayControllerTest {
    @Resource
    PlayController playController;

    @After
    public void tearDown() throws Exception {
    }

    @Test
    public void play() {
        playController.play();

    }
}

//有一些自动生成的函数没有删除

single play

说明成功地将对应的bean以构造函数的方式注入。

2. 参数依赖类型有多实现类情况下的注入方式

单构造函数参数依赖的类型,有多个实现类时,就不能直接像上面的例子一样,只定义接口的类型了:

以下方式是错误的:

public MorePlayContorller(MorePlay morePlay) {
morePlay.someOnePlay();
}

需要写明所引用的bean的名称,否则spring根据type匹配到两个bean,就会报错。

看下实际的例子:

import org.springframework.stereotype.Component;

@Component
public class MorePlayImplFirstOne implements MorePlay {
    @Override
    public void someOnePlay() {
        System.out.println("\n\nFirst one play.\n\n");
    }
}
import org.springframework.stereotype.Component;

@Component
public class MorePlayImplSecondOne implements MorePlay {
    @Override
    public void someOnePlay() {
        System.out.println("\n\nSecond one play.\n\n");
    }
}
import org.springframework.stereotype.Component;

@Component
public class MorePlayContorller {

    private MorePlay morePlay;

    public MorePlayContorller(MorePlay morePlay) {
        morePlay.someOnePlay();
    }

}
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

@RunWith(SpringRunner.class)
@SpringBootTest
public class MorePlayContorllerTest {
    @Resource MorePlayContorller morePlayContorller;

    @Test
    public void play() {
        morePlayContorller.play();
    }
}
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.springbootexample.oneArgument.MultiImplementation.MorePlay' available: expected single matching bean but found 2: morePlayImplFirstOne,

很显然,直接就懵圈了,我找到了两个,你是想要哪一个?实际上,这种方式编译都过不了。

@Component
public class MorePlayContorller {

    private MorePlay morePlay;

    public MorePlayContorller(@Qualifier("morePlayImplFirstOne") MorePlay morePlay) {
        this.morePlay = morePlay;
    }

    public void play(){
        morePlay.someOnePlay();
    }

}

方式二:构造函数中的属性名与所要注入的bean名称一致


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

@Component
public class MorePlayContorller {

    private MorePlay morePlay;

    public MorePlayContorller(@Qualifier("morePlayImplFirstOne") MorePlay morePlay) {
        this.morePlay = morePlay;
    }

    public void play(){
        morePlay.someOnePlay();
    }

}
First one play

3. list注入方式

当具体业务场景中,需要依赖于某接口的所有实现类时,可以使用list注入,构造函数方式注入,同样也可以注入list。

import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class ListPlayControler {

    private List<MorePlay> goPlays;

    public ListPlayControler(List<MorePlay> goPlays) {
        this.goPlays = goPlays;
    }

    public void listPlay(){
        goPlays.forEach(goPlay -> goPlay.someOnePlay());
    }

}
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ListPlayControlerTest {

    @Resource private ListPlayControler listPlayControler;

    @Test
    public void listPlay() {
        listPlayControler.listPlay();
    }
}
First one play.

Second one play.

4. 构造函数多参数依赖情况下的注入方式

import com.example.springbootexample.oneArgument.MultiImplementation.MorePlay;
import com.example.springbootexample.oneArgument.SingleImplementation.GoPlay;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class PlayMoreArugumentContoller {
    private GoPlay goPlay;
    private MorePlay morePlay;

    public PlayMoreArugumentContoller(GoPlay goPlay, @Qualifier("morePlayImplSecondOne") MorePlay morePlay) {
        this.goPlay = goPlay;
        this.morePlay = morePlay;
    }

    public void playAll(){
        goPlay.havePlay();
        morePlay.someOnePlay();

    }
}
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

@RunWith(SpringRunner.class)
@SpringBootTest
public class PlayMoreArugumentContollerTest {

    @Resource private PlayMoreArugumentContoller playMoreArugumentContoller;

    @Test
    public void playAll() {
        playMoreArugumentContoller.playAll();
    }
}
single play

Second one play.
推荐阅读:
  1. spring 常用的注入方式有哪些?
  2. 详解Spring基于xml的两种依赖注入方式

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

javaspring 方式详解 sprin

上一篇:Maven项目部署到Jboss出现Failed to create a new SAX parser

下一篇:C#实现谷歌翻译API示例代码

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》