美文网首页
Spring IOC&DI概述

Spring IOC&DI概述

作者: BlueSkyBlue | 来源:发表于2020-03-17 18:18 被阅读0次

    IOC(Inversion of Control)

    其思想是反转资源获取的方向。传统的资源查找方式要求组件向容器发起请求查找资源。作为回应,容器适时的返回资源。而使用了IOC之后,是容器主动将资源推送给它管理的组件,组件所需要做的则是选择一种合适的方式来接收资源。这种行为也被称为查找的被动形式。

    DI(Dependency Injection)

    IOC的另一种表述方式,即组件以一些预先定义好的方式(例如Setter)接收来自容器的资源注入。相比于IOC而言,这种表述更为直接。

    通过XML的方式进行IOC有一个缺陷就是必须要有一个无参的构造器。如果要创建的Bean中的构造器是有参的则抛出异常。

    DI实例

    <bean id="helloWorld" class="com.spring.beans.HelloWorld">
        <property name="name" value="Spring"></property>
    </bean>
    

    class: bean的全类名,通过反射的方法在IOC容器中创建bean。所以要求Bean中必须有无参构造函数。
    id: 标识容器中的bean, id唯一。

    Spring容器

    ApplicationContext代表IOC容器。但是它实际上是一个接口。

    在Spring IOC容器读取Bean,配置Bean,创建Bean实例之前必须要对它进行实例化。只有在容器实例化之后才可以从IOC容器中获取Bean实例并使用。

    Spring提供了两种类型的IOC容器的实现:

    • BeanFactory:IOC容器的基本实现
    • ApplicationContext:提供了更多的高级特性。是BeanFactory的子接口。

    BeanFactory是Spring框架的基础设施,面向Spring本身。ApplicationContext面向使用Spring框架的开发者本身。几乎所有的应用场合都使用ApplicationContext而非BeanFactory。

    无论使用何种方式,配置文件时都是相同的。

    ApplicationContext

    ApplicationContext继承关系

    ApplicationContext的主要实现类有

    • ClassPathXmlApplicationContext:从类路径下加载配置文件。
    • FileSystemXmlApplicationContext:从文件系统中加载配置文件。

    ConfigurableApplicationContext扩展于ApplicationContext。新增两个主要的方法refresh()和close()。让ApplicationContext具有启动,关闭和刷新上下文的能力。

    ApplicationContext在初始化上下文时就实例化所有的单例的Bean。

    WebApplicationContext是专门为Web准备的,它允许从Web根目录的路径中完成初始化的工作。

    也可以通过类名来获取Bean,例如

    HelloWorld hello2 = applicationContext.getBean(HelloWorld.class);
    

    但是该方法有一个缺陷。就是当IOC容器中配置了两个来自同一个类的bean的时候,系统不知道要创建的是那一个bean就会抛出异常。所以要求IOC容器中只能有一个该类型的bean。

    依赖注入的方式

    • 属性注入
    • 构造器注入
    • 工厂方法注入(很少使用,不推荐)

    属性注入

    通过setter方法注入Bean的属性值或依赖的对象。
    属性名注入使用的是<property/>标签,使用name属性指定Bean的属性名称。value属性或<value/>子结点指定属性值。
    属性注入是开发中最常用的注入方式。

    构造方法注入

    通过构造方法注入Bean的属性值或依赖的对象。它保证了Bean实例在实例化之后就可以使用

    构造器注入在<constructor-agr>元素里声明属性。<constructor-arg>中没有name属性。

    使用构造器注入属性值可以指定参数的位置和参数的类型,以区分重载的构造器。

    构造器注入示例

    创建一个新的类

    public class Car {
        private String brand;
        private String corp;
        private int price;
        private int maxSpeed;
    
        public Car(String brand, String corp, int price, int maxSpeed) {
            super();
            this.brand = brand;
            this.corp = corp;
            this.price = price;
            this.maxSpeed = maxSpeed;
        }
    
        @Override
        public String toString() {
            return "Car{" +
                    "brand='" + brand + '\'' +
                    ", corp='" + corp + '\'' +
                    ", price=" + price +
                    ", maxSpeed=" + maxSpeed +
                    '}';
        }
    }
    

    配置文件中注册

    <bean id="car" class="com.spring.beans.Car">
        <constructor-arg value="Audi"></constructor-arg>
        <constructor-arg value="Shanghai"></constructor-arg>
        <constructor-arg value="300000"></constructor-arg>
        <constructor-arg value="10000"></constructor-arg>
    </bean>
    

    主函数中调用

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Car car = applicationContext.getBean(Car.class);
        System.out.println(car);
    }
    

    问题来了?如果类中有两个构造方法,如下所示:

    public class Car {
        private String brand;
        private String corp;
        private int price;
        private double maxSpeed;
    
        public Car(String brand, String corp, int price) {
            super();
            this.brand = brand;
            this.corp = corp;
            this.price = price;
        }
    
        public Car(String brand, String corp, double maxSpeed) {
            super();
            this.brand = brand;
            this.corp = corp;
            this.maxSpeed = maxSpeed;
        }
    ...
    

    我们想要使用的是第二个构造函数。此时我们可以在配置文件中指定构造参数的类型。例如

    <bean id="car" class="com.spring.beans.Car">
        <constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
        <constructor-arg value="Shanghai" type="java.lang.String"></constructor-arg>
        <constructor-arg value="10000" type="double"></constructor-arg>
    </bean>
    

    相关文章

      网友评论

          本文标题:Spring IOC&DI概述

          本文链接:https://www.haomeiwen.com/subject/amntyhtx.html