扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
本文讲解spirng三种注入方式(构造函数注入,setter注入,注解注入)中的构造函数注入。
站在用户的角度思考问题,与客户深入沟通,找到易门网站设计与易门网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:成都做网站、网站设计、企业官网、英文网站、手机端网站、网站推广、主机域名、网页空间、企业邮箱。业务覆盖易门地区。所有例子,都是以注解的方式注册bean。
关于构造函数方式注入,spring官网的说明地址为:Spring官网之构造函数注入
单参数且单实现类这是一种最简单的以构造函数的注入方式注入依赖,只要在构造函数中添加所依赖类型的参数即可,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以构造函数的方式注入。
单构造函数参数依赖的类型,有多个实现类时,就不能直接像上面的例子一样,只定义接口的类型了:
以下方式是错误的:
public MorePlayContorller(MorePlay morePlay) { morePlay.someOnePlay(); }
需要写明所引用的bean的名称,否则spring根据type匹配到两个bean,就会报错。
看下实际的例子:
public interface MorePlay {
public void someOnePlay();
}
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
当具体业务场景中,需要依赖于某接口的所有实现类时,可以使用list注入,构造函数方式注入,同样也可以注入list。
接口和实现类,我们继续沿用MorePlay及其实现。
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class ListPlayControler {
private List goPlays;
public ListPlayControler(List goPlays) {
this.goPlays = goPlays;
}
public void listPlay(){
goPlays.forEach(goPlay -> goPlay.someOnePlay());
}
}
listPlay方法会执行GoPlay接口所有实现类对方法havePlay()的重写。list的注入方式易于业务的扩展,封装的代码不会因为扩展了一个新的实现类而发生改动,完全遵循了设计模式的原则。
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.
需要依赖多接口的场景很多,这个时候仍然可以使用构造函数的注入方式。
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.
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流