11.17Spring 注入部分
本章内容
Spring 依赖注入
Spring 注入内部Bean
Spring 注入集合
Spring 依赖注入
什么是依赖注入?
- 
依赖注入( Dependency Injection, DI),便于管理和测试应用程序
实现原理:
- 
在 Java程序中当一个Java示例需要调用另一个Java实例的方法的时候需要手动new一个对象,通过对象去调用它的方法。
- 
Spring框架中,被调用者实例由Spring容器创建,不再是调用者创建。这一过程被称为控制反转
Spring实现过程:
- 
Spring容器在创建被调用者的实例时会自动将调用者需要的对象实例注入给调用者。
- 
调用者通过 Spring容器获得被调用者实例
依赖注入的实现方式
设值注入(
setter)
构造函数注入
构造函数注入:
概念:
IoC容器使用构造函数注意被依赖的实例。每一个参数代表一个依赖
setter注入:
概念:
IoC容器使用setter方法注入被依赖实例。
实现原理:
调用无参构造器或无参static工厂方法实例化Bean后,调用该Bean的setter方法
Spring实例化Bean的过程:
- 
调用默认的(无参)构造方法实例化 Bean
- 
通过 Java反射机制调用对应的setXxx()方法为属性注入值
由上述可知setter注入的条件:
- 
提供一个默认的无参构造方法 
- 
为需要注入的属性提供对应的 set方法
在Spring配置文件中的使用:
- 
为属性注入值:使用 <bean>的子元素<property>
- 
构造注入值:使用 <constructor-arg>标签定义构造方法。使用value设置该参数的值
构造函数注入
实现:
- 
使用 <constructor-age>标签实现构造函数注入
标签包含ref、value、type、index等属性。value属性用于注入基本数据类型以及字符串类型的值;ref属性用于注入已经定义好的 Bean;type属性用来指定对应的构造函数,当构造函数有多个参数时,使用index属性指定参数的位置,index属性值从 0 开始。
示例:
- 
重构 MainApp类,新增Person和Main类
Man:
package com.bean;
/**
 * @description:Man类作为一个基类也是一个Bean对象
 * @data: 2021/11/17 16:02
 * @author: Lucfier
 */
public class Man {
    private String name;
    private int age;
    /* 提供set和get方法 */
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
    /* 提供show方法 */
    public void show() {
        System.out.println("名称 :" + name + "\n年龄 :" + age);
    }
    /* 提供空参和带参构造方法 */
    public Man(){
        System.out.println("在Man的构造函数内!");
    }
    public Man(String name, int age) {
        System.out.println("在Man的带参构造函数内!");
        this.name = name;
        this.age = age;
    }
}
Person:
package com.bean;
/**
 * @description:创建Person类作为一个新增的Bean类
 * @data: 2021/11/17 16:00
 * @author: Lucifer
 */
public class Person {
    private Man man;
    public Person(Man man) {
        System.out.println("在Person的有参构造器内!");
        this.man = man;
    }
    public void man() {
        man.show();
    }
}
MainApp:
package com.junkingboy;
import com.bean.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @description:获取Spring当中的Bean.xml配置文件下的类和属性信息
 * @data: 2021/11/15 11:20
 * @author: Lucifer
 */
public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        Person person = (Person) context.getBean("person");
        person.man();
    }
}
Beans.xml:
结论:
- 
出现的顺序是会先初始化 Man的Bean对象,因为在Person的Bean对象里面引用了Man的Bean配置。
- 
<constructor-age>标签设置的值相当于定义了两个形参去实例化Man类,通过Man类的带参构造器。
- 
构造好了 Man类的对象以后由于Person person会将Man对象作为参数带到Person类的带参构造器中。
- 
在使用 Person构造器返回的Man类对象调用Man下的Show()方法
setter注入
实现:
- 
使用 <property>标签
标签包含name、ref、value等属性。name用于指定参数名称;value属性用于注入基本数据类型以及字符串类型的值;ref属性用于注入已经定义好的Bean。
示例:
- 
修改 Person类
package com.bean;
/**
 * @description:创建Person类作为一个新增的Bean类
 * @data: 2021/11/17 16:00
 * @author: Lucifer
 */
public class Person {
    private Man man;
    /* 提供get和set方法 */
    public Man getMan() {
        return man;
    }
    public void setMan(Man man) {
        System.out.println("在setMan方法内!");
        this.man = man;
    }
    public void man() {
        man.show();
    }
}
结论:
- 
该写法实际在 Bean的初始化顺序和上一个写法没区别
- 
在 Spring Bean处使用的标签和上一个有所不同
Spring注入内部Bean
什么是Spring内部Bean?
- 
在 Java类内部定义的类称为内部类,在Spring的Bean内部定义的Bean称为Spring内部Bean
特点:
- 
不需要指定 id和name。如果指定了,容器不会将其作为区分Bean的标识符,会无视内部Bean的scope属性。所以内部Bean总是匿名的,而且总是随着外部Bean创建。
在实际开发中很少注入内部 Bean,因为开发者无法将内部的 Bean 注入外部 Bean 以外的其它 Bean。
实现:
- 
注入内部 Bean使用<property>和<constructor-arg>中的<bean>标签。
示例:
Spring注入集合
概念:
Spring注入集合的意思是需要传递Java Collection类型的值
方式:
使用Spring提供的集合配置标签
| 标签 | 说明 | 
|---|---|
| <list> | 用于注入 list 类型的值,允许重复 | 
| <set> | 用于注入 set 类型的值,不允许重复 | 
| <map> | 用于注入 key-value 的集合,其中 key-value 可以是任意类型 | 
| <props> | 用于注入 key-value 的集合,其中 key-value 都是字符串类型 | 
示例:
- 
新建 JavaCollection类
package com.junkingboy;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
 * @description:该类主要是java的list等属性
 * @data: 2021/11/17 18:24
 * @author: Lucifer
 */
public class JavaCollection {
    List manList;
    Set manSet;
    Map manMap;
    Properties manProp;
    /* 提供get和set方法 */
    public List getManList() {
        System.out.println("List Elements :" + manList);
        return manList;
    }
    public Set getManSet() {
        System.out.println("Set Elements :" + manSet);
        return manSet;
    }
    public Map getManMap() {
        System.out.println("Map Elements :" + manMap);
        return manMap;
    }
    public Properties getManProp() {
        System.out.println("Properties Elements :" + manProp);
        return manProp;
    }
    public void setManList(List manList) {
        this.manList = manList;
    }
    public void setManSet(Set manSet) {
        this.manSet = manSet;
    }
    public void setManMap(Map manMap) {
        this.manMap = manMap;
    }
    public void setManProp(Properties manProp) {
        this.manProp = manProp;
    }
}
Bean.xml:
 
                     
                    
                 
                    
                