齐齐哈尔人才网:Spring IOC的焦点机制:实例化与注入

admin 6个月前 (05-05) 科技 42 0

上文我们先容了IOC和DI,IOC是一种设计模式,DI是它的详细实现,有许多的框架都有这样的实现,本文主要以spring框架的实现,来看详细的注入实现逻辑。

spring是如何将工具加入容器的

spring将工具加入容器的方式有许多种,最主要的是xml和注解的形式,而当下注解的形式应用加倍的普遍,以是这里我们也主要先容注解注入模式下的相关知识点。

spring下的注解也是有许多种的,其中应用最为普遍的就是模式注解。

模式注解 stereotype annotations

咋一看,这是啥,说实话我也不太清晰,官方说的就叫这哈,实在他说的就是平时最常用的那些 @Component @Service @Controller @Repository @Configuration 注解。

若是一个类被打上 @Component注解,那他就会被容器扫描到并加入到容器里去。那这里我们用spring的方式再来实现一下上篇文章的获取英雄的需求。

先给 Diana这个英雄打上一个 @Component注解:

@Component
public class Diana{
    private String skillName = "Diana R";

    public Diana() {
    }

    public void q(){
        System.out.println("Diana Q");
    }

    public void w(){
        System.out.println("Diana W");
    }

    public void e(){
        System.out.println("Diana E");
    }

    public void r(){
        System.out.println(this.skillName);
    }
}

假设现在有一个Controller需要用到 Diana

@RestController
public class BannerController {

    @Autowired
    private Diana diana;

    @RequestMapping(value = "/v2/banner", method = {RequestMethod.GET})
    public String test() {
        diana.r();
        return "Hello SpringBoot";
    }
}

@Autowired的意思就是说在这里注入一个工具,然后我们启动应用,

通过浏览器接见 http://localhost:8081/v2/banner,会发现在控制台会输出 Diana的r方式的打印内容,说明这里确实拿到了 Diana这个工具。

工具的注入时机

若是我们把 Diana@Component注解去掉,其他地方稳定,再运行程序会发生什么,试试看。

重新启动的时刻会提醒我们下面的错误:

看错误提醒,说程序没有找到对应的bean,就是说我这里要注入bean了,然则在容器里没有找到。

这里就会得出一个结论:容器在初始化后就会给响应的代码片断举行工具的注入

从提醒信息中可以看到Autowired(required=true),这里设置的默认是true,示意注入的时刻,该工具必须存在,否则就会注入失败。固然这里可设置不报错,Autowired(required=false),这个时刻再启动就不会报错了,然则在接见的时刻会报空指针异常。

那这里spring的容器究竟是在什么时刻实例化的工具呢,是在接见controller的时刻呢,照样在容器启动的时刻呢?我们可以通过下面的手段检测一下,在 Diana的无参组织方式中放一个打印语句,然后再启动程序:

public Diana() {
    System.out.println("I am Diana");
}

程序启动以后,会看到在控制台会显示出组织方式中打印的语句

这就说明在容器启动后把类加载到容器以后,就会实例化一个工具出来。这就又得出一个结论:容器初始化以后就会对bean举行实例化

工具的延迟注入

上面提到容器在确定后就会把工具(也就是bean)实例化,那有没有办法让他不马上实例化?

spring提供了@Lazy这个注解,用以解释某个bean可以延迟加载,用之前的 Diana延时一下,给他加上@Lazy这个注解:

@Component
@Lazy
public class Diana{
    private String skillName = "Diana R";

    public Diana() {
        System.out.println("I am Diana");
    }

    public void q(){
        System.out.println("Diana Q");
    }

    public void w(){
        System.out.println("Diana W");
    }

    public void e(){
        System.out.println("Diana E");
    }

    public void r(){
        System.out.println(this.skillName);
    }
}

再次启动程序,会发现在控制台照样会执行组织方式里的打印语句,这是什么情况,不是明显已经加了延迟加载了么?

这里会设计到spring的一个机制,就是说若是某个bean没有设置延迟加载,这个bean会在容器启动就实例化,而且这个bean内里所依赖的其他bean都市举行过实例化,纵然设置了懒加载。

我们在BannerController里用到了 Diana这个bean,并把它设置了延迟加载,然则并没有把BannerController也设置成延迟加载,以是容器再实例化BannerController的时刻同样会 Diana这个bean举行实例化。若是要真正做到延迟加载,需要让BannerController也要延迟加载。给它加上@Lazy以后,再启动看一下:

这个时刻控制就没有那条打印语句的输出内容了,此时我们通过浏览器来接见BannerController的路由,此时就会在控制台输出组织方式里打印语句的输出内容了。

工具的注入逻辑

上文 Diana的就是一个单独的类,没有实现任何接口,这种实现方式他是有问题的,很难举行扩展,这里不应该一类详细的实现类,而是要应该依赖抽象,这样才气知足开闭原则,让程序具有优越的扩展性。

这里让 Diana实现了一 Skill接口,

public interface Skill {
    void q();
    void w();
    void e();
    void r();
}

在BannerController注入这里也要改一下:

@Autowired
private Skill diana;

运行程序,发先能够运行乐成,若是新添加一个英雄的实现类:

@Component
public class Irelia implements Skill {

    public Irelia() {
        System.out.println("Hello, Irelia");
    }
    public void q(){
        System.out.println("Irelia Q");
    }

    public void w(){
        System.out.println("Irelia W");
    }

    public void e(){
        System.out.println("Irelia E");
    }

    public void r(){
        System.out.println("Irelia R");
    }
}

我们再去运行程序,发现照样能运行乐成,而且发现注入的是 Diana而不是 Irelia,那这里我们可能会问为什么呀,前面似乎也没指定注入哪个实现类。

岂非是由于 private Skill diana;这里写了 diana么?你还别说,还真是这个缘故原由,这里涉及到spring的注入机制了。

当spring的IOC容器注入bean的时刻,若是发现有多个相同类型的bean时,就会去看它们的名称(name),若是名称符合要求,就会注入这个名称的bean。每个被容器扫描到的bean都市有一个默认的name,就是它的类名,首字母会小写,好比我们实例中的:BannerController的name就是bannerController,Irelia就是irelia。

可以试着把 private Skill diana改成 private Skill skill,再次运行,就会发生报错:

齐齐哈尔人才网:Spring IOC的焦点机制:实例化与注入 第1张

提醒你找不到响应的bean。这里要明确一点哈,虽然报错了,然则这种写法是尺度的,上面谁人直接写实现类的名字不是尺度的写法。

那怎么解决这个找不到的问题呢?

spring提供了一个@Qualifier的注解,给他传入要注入bean的名字,就可以指定注入的bean,@Qualifier("irelia")。

总结

Autowired的注入方式有两种,一种是根据类型注入,一种是根据名称注入,默认是根据类型注入,若是只有一个实现类 Diana,这里写成 private Skill skill,运行程序,你会发现是能够注入乐成的。由于Skill类型下只有一个实现类,自然就是注入它了。若是有多个实现类,那就会先根据这个类型查找,这个类型下所有到的实现类再根据名称查找,直至找到符合要求的,找不到就报错。

更多关于spring IOC内容,请查看(博客网站)[https://www.immortalp.com]

迎接人人去 我的博客 瞅瞅,内里有更多关于测试实战的内容哦!!

,

阳光诚信在线平台

阳光诚信在线官网(原诚信在线官网)现已开放阳光在线手机版、阳光在线电脑客户端下载。阳光在线娱乐戏公平、公开、公正,用实力赢取信誉。

AllBetGaming声明:该文看法仅代表作者自己,与本平台无关。转载请注明:齐齐哈尔人才网:Spring IOC的焦点机制:实例化与注入

网友评论

  • (*)

最新评论

文章归档

站点信息

  • 文章总数:669
  • 页面总数:0
  • 分类总数:8
  • 标签总数:1075
  • 评论总数:254
  • 浏览总数:7763