自学内容网 自学内容网

Spring IoC&DI

一.IoC&DI简单介绍

        IoC叫控制反转,是一种设计原则,降低代码的耦合度。简单的举例:在未使用IoC设计原则时,对象的创建是使用方进行管理的,也就导致对象的控制权在使用方手里,但使用了IoC设计原则之后,就会有一个外部容器(Spring)来进行统一管理和创建,使用方不再管理对象的创建和依赖关系,也就失去了控制权,控制权就给了IoC容器,这就是控制反转。

        DI是依赖注入。

二.控制反转的简单例子和使用

1.未使用IoC设计理念时的一个代码:

public class Tire {
    private int size;

    public Tire(int size) {
        System.out.println("Tire size: " + size + " Init...");
    }
}



public class Bottom {
    private Tire tire;

    public Bottom(int size) {
        this.tire = new Tire(size);
        System.out.println("Tire Init...");
    }
}


public class FrameWork {
    private Bottom bottom;

    public FrameWork(int size) {
        this.bottom = new Bottom(size);
        System.out.println("FrameWork Init...");
    }
}




public class Car {
    private FrameWork frameWork;

    public  Car(int size) {
        this.frameWork = new FrameWork(size);
        System.out.println("Car Init...");
    }

    public void run() {
        System.out.println("run...");
    }
}


public class Main {
    public static void main(String[] args) {
        Car car = new Car(20);
        car.run();
    }
}



        当使用了IoC设计原则时,对象的创建和管理都是统一在一起的,并且也降低了代码的耦合性,像上图中的代码中,当Tire创建新的字段并成为构造方法的参数时,调用了Tire对象的每个使用方都需要在里面加上新的参数,而IoC设计原则就是这方面代码的耦合性降低了很多,代码如下:

public class Tire {

    private int size;

    public Tire(int size) {
        System.out.println("Tire size: " + size + " Init...");
    }
}


public class Bottom {
    private Tire tire;

    public Bottom(Tire tire) {
        this.tire = tire;
        System.out.println("Tire Init...");
    }
}


public class FrameWork {
    private Bottom bottom;

    public FrameWork(Bottom bottom) {
        this.bottom = bottom;
        System.out.println("FrameWork Init...");
    }
}



public class Car {
    private FrameWork frameWork;

    public  Car(FrameWork frameWork) {
        this.frameWork = frameWork;
        System.out.println("Car Init...");
    }

    public void run() {
        System.out.println("run...");
    }
}





public class Main {
    public static void main(String[] args) {
        Tire tire = new Tire(20);
        Bottom bottom = new Bottom(tire);
        FrameWork frameWork = new FrameWork(bottom);
        Car car = new Car(frameWork);
        car.run();
    }
}

2.使用了IoC设计原则并且使用注释来写代码:

其中Component注解是Spring统一管理对象的创建和依赖,Autowired是使用Spring统一管理的对象

3.Bean简单说明:

        使用Bean注解或者下方所说的衍生注解,作用于类时,就会将这些类的对象交给Spring来进行管理,对象本身不需要负责对象的创建和依赖。(在userInfo2的方法中,参数的名字也必须和Spring管理的方法的方法名一样,如果不相同就无法使用。)

三.Bean的存储

1.Controller注解(控制器存储)

        被Controller修饰的类,则其对象会被Spring统一管理,并且RestController也可以做到同样的效果。

2.获取Bean对象的其他方式

(1)根据bean的名称获取bean:

bean名称在官方文档中有规定的:

简单的来说,bean的名字当为null或者长度为0时,直接返回这个name,当name的长度大于1,并且第一个和第二个单词都是大写的name也是直接返回name,其他情况都是将name先转换成字符数组,在将第一个字母改为小写,最后转换成字符串返回name。

(2)根据bean的名字和类型获取bean

(3)根据类型获取bean,一般用于只有一个对象

也因此,Spring涉及的模式是单例模式。

四.其余注解

1.Service

2.Configuration

3.Component

4.Repository

以上获取bean的方式都与UserController相同,并且Controller,Service,Repository,Configuration都是Component的衍生注解。

五.Bean注解

1.当需要使用外部包的类时,没办法添加类注解和一个类,需要多个对象,比如数据源时,需要通过Bean方法注解获得对象(假设UserInfo是外部包的类,因为在UserInfoComponent的类中存在两个对象,若果通过类型获取,则不知道获取那个对象,所以必须通过方法名来获取):

2.重命名Bean

可以通过Bean改变方法的名字,在新的名字字符串数组中选取其中一个就可以来进行获取对象(简便的写法可以把name = 给省略了,当只有一个字符串的时候可以不用写{})。

3.扫描路径:@ComponentScan

        当启动类的路径和需要使用的第三方包不在同一个路径是,需要调用第三方的包,就可以使用@ComponentScan({“”})来往其中输入路径来进行扫描,并且括号里面是一个字符串数组,则可以写多个路径来扫描:

六.DI依赖注入

1.属性注入

Autowired直接作用于类的属性,就是属性注入,Spring管理的对象就能够直接使用。

2.构造方法注入

        存在多个构造方法时,需要指定默认的构造方法就是用Autowired来进行指定。

3.setter方法注入

        同样使用Autowired,让程序能进入set方法,并且从Spring中拿取对象。

4.三种注入方式优缺点

属性注⼊
◦ 优点:简洁,使⽤⽅便;
◦ 缺点:
▪ 只能⽤于IoC容器,如果是⾮IoC容器不可⽤,并且只有在使⽤的时候才会出现NPE(空指
针异常)
▪ 不能注⼊⼀个Final修饰的属性


• 构造函数注⼊(Spring4.X推荐)
◦ 优点:
▪ 可以注⼊final修饰的属性
▪ 注⼊的对象不会被修改
▪ 依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法
是在类加载阶段就会执⾏的⽅法.
▪ 通⽤性好,构造⽅法是JDK⽀持的,所以更换任何框架,他都是适⽤的
◦ 缺点:
▪ 注⼊多个对象时,代码会⽐较繁琐


• Setter注⼊(Spring3.X推荐)
◦ 优点:⽅便在类实例之后,重新对该对象进⾏配置或者注⼊
◦ 缺点:
▪ 不能注⼊⼀个Final修饰的属性
▪ 注⼊对象可能会被改变,因为setter⽅法可能会被多次调⽤,就有被修改的⻛险。

七.Autowired出现的问题

1.同样类型,有多个名称对象时,按照名称来匹配

2.当该类型只有一个对象时,就直接注入

3.在1.的情况下,没有名称匹配

(1)通过注解Primary来确定默认的对象:

(2)通过@Qualifier来对注入的时候进行指定对象:

(3)当传入参数名不在Spring中时,需要确定一个默认的参数的方法:

1. 通过Primary确定默认参数:

2.通过Qualifier在传递参数时指定某个参数:

(4)使用JDK的注解Resource

 使用JDK的Resource注解可以指定我们使用的是哪个方法:

八.Resource和Autowired的区别

1.Resource根据名称匹配,Autowired根据类型匹配:这句话的意思只不过代表着,同类型时的多个对象,Resource是根据名称优先匹配,再根据类型进行匹配,Autowired则是先通过类型进行匹配,再进行名称进行匹配,着重去理解其中原理。

2.Autowired和Resource的基本原则都是根据类型进行匹配,只是Resource可以指定名称,而Autowired无法根据名称匹配。所谓指定根据名称进行匹配,指定是Resource的括号里可以写name = “对象名称”进行匹配,但Autowired无法指定对象名称。而不是所谓的变量名的名称。

3.Resource可以粗糙的说等于Autowired + Qualifier。

4.Resource是JDK提供的注解,Autowired是Spring提供的注解。

5,Autowired的装配顺序:


原文地址:https://blog.csdn.net/wk200411/article/details/145088271

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!