码迷,mamicode.com
首页 > 编程语言 > 详细

Spring依赖注入

时间:2020-10-16 10:55:46      阅读:22      评论:0      收藏:0      [点我收藏+]

标签:sch   his   out   contex   调用bean   设值   依赖   encoding   ram   

Spring依赖注入

Spring的IOC(Inversion Of Control 控制反转)是通过DI(Dependency Injection 依赖注入)实现的,依赖注入在Spring主要有以下几种方式:

技术图片

一、基于XML的依赖注入

基于XML的依赖注入,指的是修改XML配置文件来实现依赖注入,主要包括setter设值注入和构造注入,另外还有一种自动注入,自动注入主要是针对引用类型属性的注入。

我们对XML依赖注入的讨论基于以下类和测试:

public class Staff {
    private String name;
    private int age;
    private Company company;

    public Staff() { }

    public Staff(String name, int age, Company company) {
        this.name = name;
        this.age = age;
        this.company = company;
    }

    public void setName(String name) { this.name = name; }

    public void setAge(int age) { this.age = age; }

    public void setCompany(Company company) { this.company = company; }
    
    @Override
    public String toString() {
        return "Staff{" +
                "name=‘" + name + ‘\‘‘ +
                ", age=" + age +
                ", company=" + company +
                ‘}‘;
    }
}
public class Company {
    private String name;
    private String address;

    public Company() { }

    public Company(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public void setName(String name) { this.name = name; }

    public void setAddress(String address) { this.address = address; }

    @Override
    public String toString() {
        return "Company{" +
                "name=‘" + name + ‘\‘‘ +
                ", address=‘" + address + ‘\‘‘ +
                ‘}‘;
    }
}
public class AppTest {
    @Test
    public void Test() {
        String resource = "ApplicationContext.xml";
        ApplicationContext context = new ClassPathXmlApplicationContext(resource);
        Staff staff = (Staff) context.getBean("Staff");
        System.out.println(staff);
    }
}

1、设值注入

使用

设值注入通过标签完成,它有namevalueref属性。

属性:

name: 属性名

value: 简单类型值

ref: 引用类型值


  • 对简单类型(基本类型 + String)的属性,使用namevalue属性:

    <property name="属性名" value="属性值"/>
    
  • 对引用类型的属性,使用nameref属性:

    <property name="属性名" ref="引用类型<bean>id属性值"/>
    

示例

技术图片

测试

技术图片

原理

我们在StaffCompany的无参构造函数和各属性setter方法中打印一些提示信息,以便于我们观察整个注入流程:

public class Staff {
    private String name;
    private int age;
    private Company company;

    public Staff() {
        System.out.println("Staff‘s non-arg constructor."); //提示信息
    }

    public Staff(String name, int age, Company company) {
        this.name = name;
        this.age = age;
        this.company = company;
    }

    public void setName(String name) {
        System.out.println("Staff‘s setName " + name); //提示信息
        this.name = name;
    }

    public void setAge(int age) {
        System.out.println("Staff‘s setAge " + age); //提示信息
        this.age = age;
    }

    public void setCompany(Company company) {
        System.out.println("Staff‘s setCompany " + company); //提示信息
        this.company = company;
    }

    @Override
    public String toString() {
        return "Staff{" +
                "name=‘" + name + ‘\‘‘ +
                ", age=" + age +
                ", company=" + company +
                ‘}‘;
    }
}
public class Company {
    private String name;
    private String address;

    public Company() {
        System.out.println("Company‘s non-arg constructor."); //提示信息
    }

    public Company(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public void setName(String name) {
        System.out.println("Company‘s setName " + name); //提示信息
        this.name = name;
    }

    public void setAddress(String address) {
        System.out.println("Company‘s setAddress " + address); //提示信息
        this.address = address;
    }

    @Override
    public String toString() {
        return "Company{" +
                "name=‘" + name + ‘\‘‘ +
                ", address=‘" + address + ‘\‘‘ +
                ‘}‘;
    }
}

  • Spring会先调用bean的无参构造函数,然后调用属性的setter方法,完成注入

运行观察:

技术图片

TODO:至于对象的创建顺序,这里挖一个坑,以后再填。

  • Spring是通过将"set"和标签中的name属性(首字符变大写)拼接形成的方法名来调用setter方法,例如:
<property name="age" value="19"/> <!--调用setAge方法-->
<property name="company" ref="Company"/> <!--调用setCompany方法-->

此时我们向Staff的标签中再添加一个标签:

技术图片

Staff类中增加setAny方法(但没有any属性):

技术图片

运行观察:

技术图片

2、构造注入

使用

构造注入通过标签完成。它有nameindexvalueref属性。

属性:

name: 形参名

index: 形参位置, 从0开始

value: 简单类型值

ref: 引用类型值

  • 对简单类型:

    <constructor-arg name="形参名" value="形参值"/>
    
    <constructor-arg index="形参位置,从0开始" value="形参值"/>
    
  • 对引用类型:

    <constructor-arg name="形参名" ref="引用类型<bean>id属性值"/>
    
    <constructor-arg index="形参位置,从0开始" ref="引用类型<bean>id属性值"/>
    

示例

技术图片

测试

技术图片

原理

我们在StaffCompany的有参构造函数中打印一些提示信息,以便于我们观察整个注入流程:

public class Staff {
    private String name;
    private int age;
    private Company company;

    public Staff() { }

    public Staff(String name, int age, Company company) {
    	System.out.println("Staff‘s arg constructor."); //提示信息
        this.name = name;
        this.age = age;
        this.company = company;
    }

    public void setName(String name) { this.name = name; }

    public void setAge(int age) { this.age = age; }

    public void setCompany(Company company) { this.company = company; }
    
    @Override
    public String toString() {
        return "Staff{" +
                "name=‘" + name + ‘\‘‘ +
                ", age=" + age +
                ", company=" + company +
                ‘}‘;
    }
}
public class Company {
    private String name;
    private String address;

    public Company() { }

    public Company(String name, String address) {
        System.out.println("Company‘s arg constructor."); //提示信息
        this.name = name;
        this.address = address;
    }

    public void setName(String name) { this.name = name; }

    public void setAddress(String address) { this.address = address; }

    @Override
    public String toString() {
        return "Company{" +
                "name=‘" + name + ‘\‘‘ +
                ", address=‘" + address + ‘\‘‘ +
                ‘}‘;
    }
}

  • Spring会调用对应的有参构造函数,完成注入

运行观察:

技术图片

TODO:至于对象的创建顺序,这里挖一个坑,以后再填。


3、自动注入

自动注入是针对引用类型属性的注入。当我们的bean中引用类型的数据过多时,就会出现下面这种画风:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="xxx" class="xxx.xxx.xxx">
    	<property name="..." ref="..."/>
        <property name="..." ref="..."/>
        <property name="..." ref="..."/>
        <property name="..." ref="..."/>
        ...
    </bean>

    <bean id="xxx" class="xxx.xxx.xxx">
        ...
    </bean>
    
    <bean id="xxx" class="xxx.xxx.xxx">
        ...
    </bean>

    <bean id="xxx" class="xxx.xxx.xxx">
        ...
    </bean>
    ...
</beans>

ref引用的都是其他,那我们有什么办法让Spring自己在配置文件中搜索相应的,并注入到相应属性当中去呢?Spring提供了byNamebyType两种方法。

准备工作

  • 为了完成此部分的分析,我们添加一个Company的子类InternetCompany

    public class InternetCompany extends Company {
        public InternetCompany() {
            System.out.println("InternetCompany‘s non-arg constructor");
        }
        
        public InternetCompany(String name, String address) {
            super(name, address);
            System.out.println("InternetCompany‘s arg constructor");
        }
    }
    
  • 类型同源:

    • 相同类型
    • A是B的父类
    • A是接口,B是其实现类

使用

  • byName

    byName通过在标签中将autowire属性设为byName实现,Spring会查找和属性同名的标签,如果类型同源则注入。因为有标签id属性和类属性同名的限制,所以如果有多个同源也无所谓。

  • byType

    byType通过在标签中将autowire属性设为byType实现,Spring会查找同源bean,并注入。不可以有多个同源标签。

示例

  • byName
技术图片
  • byType
技术图片

测试

  • byName
技术图片
  • byType
技术图片

二、基于注解的依赖注入

TODO:填个坑

Spring依赖注入

标签:sch   his   out   contex   调用bean   设值   依赖   encoding   ram   

原文地址:https://www.cnblogs.com/YuHover/p/SpringDI.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!