Spring IOC详解

一、IOC

1. 什么是IOC

  • 控制反转,把对象创建核对对象之间的调用过程,交给Spring进行管理

2. IOC的目的

  • 为了耦合度降低

3. IOC的底层原理

  • xml解析
  • 工厂模式
  • 反射

4. IOC过程

  • 创建xml配置文件,配置创建的对象
  <bean id="user" class="com.github.entity.User" >   </bean>
  • 创建工厂类
class UserFactory{
      public static User getUser(){
           String class = class的属性值  // xml解析获得类的名称
           Class clazz = Class.forName(class); //通过反射创建对象
           return (User)clazz.newInstance();
      }
 }

5. BeanFactory接口

  • IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
  • Spring提供IOC容器实现的俩种方式——两个接口
  1. BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用
    加载配置文件时候不会创建对象,在获取对象使用才去创建对象
  2. ApplicationContext:BeanFactory的子接口,提供更多更强大的功能,一般由开发人员进行使用
    加载配置文件时候就会把配置文件的对象进行创建
  3. ApplicationContext接口有实现类

在这里插入图片描述

二、IOC操作Bean管理

1. 什么是Bean管理

  • Spring创建对象
  • Spring注入属性

2. Bean管理的两种操作方式

  • 基于xml配置方式实现
  • 基于注解方式实现

3. 基于XML方式

3.1 创建对象

  • 首先创建一个User类
public class User {
    private String name;
    private Integer age;
    private String gender;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public User(String name, Integer age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public User(){

    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }

    public void add(){
        System.out.println("hello");
    }
}
  • 配置xml文件
<bean id="user" class="com.github.entity.User"></bean>
  • 在Spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
  • 在bean标签里有很多属性,下面是常用的属性
  1. id属性:唯一标识
  2. class属性:类全路径
  3. name属性:也是标识,里面可以存在特殊字符
  4. scope属性:确定是否为单例对象

3.2 注入属性

  • DI:依赖注入,就是注入属性
3.2.1 set 方式注入
  • 配置xml文件
<!-- set注入属性 -->
<bean id="user" class="com.github.entity.User">
    <!-- 使用property完成属性注入
           name: 类里面属性名称
           value:向属性注入的值
    -->
    <property name="name" value="zhangsan"></property>
    <property name="age" value="15"></property>
    <property name="gender" value="男"></property>
</bean>
3.2.2 使用有参构造进行注入
  • 配置xml文件
<bean id="user1" class="com.github.entity.User">
    <constructor-arg name="name" value="wu"></constructor-arg>
    <constructor-arg name="age" value="16"></constructor-arg>
    <constructor-arg name="gender" value="女"></constructor-arg>
</bean>
3.2.3 p名称空间注入
  • 使用p名称空间注入,可以简化基于xml的配置方式
  • 添加p名称空间在配置文件中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  • 配置xml文件
<bean id="user2" class="com.github.entity.User" p:name="李四" p:age="21" p:gender="男"> </bean>
3.2.4 注入字面量
  • 扩展User类
 private String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
  • NuLL值
 <bean id="user3" class="com.github.entity.User">
        <property name="name" value="zhangsan"></property>
        <property name="age" value="15"></property>
        <property name="gender" value="男"></property>
        <property name="address">
            <null></null>
        </property>
    </bean>
  • 属性中包含特殊符号
 <bean id="user4" class="com.github.entity.User">
        <property name="name" value="zhangsan"></property>
        <property name="age" value="15"></property>
        <property name="gender" value="男"></property>
        <property name="address">
            <value><![CDATA[<<西安>>]]></value>
        </property>
    </bean>
  • 测试类结果
    在这里插入图片描述
3.2.5 注入属性-外部bean
  • 创建两个类
public class Dept {
    private String dname;

    public Dept() {
    }

    public void setDname(String dname) {
        this.dname = dname;
    }
}

public class Emp {
    private String name;
    private Integer age;

    private Dept dept;

    public Emp() {
    }

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

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

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", dept=" + dept +
                '}';
    }

}

xml配置文件

<bean id="emp" class="com.github.entity.Emp">
        <property name="name" value="zhangsan"></property>
        <property name="age" value="20"></property>
        //级联的一种
        <property name="dept" ref="dept"></property>
    </bean>

    <bean id="dept" class="com.github.entity.Dept">
        <property name="dname" value="研发"></property>
    </bean>
3.2.6 注入属性-内部bean
  • xml配置
<bean id="emp" class="com.github.entity.Emp">
        <property name="name" value="zhangsan"></property>
        <property name="age" value="20"></property>
        <property name="dept">
            <bean id="dept" class="com.github.entity.Dept">
                <property name="dname" value="研发"></property>
            </bean>
        </property>
    </bean>
3.2.7 注入属性-级联赋值
  • 级联赋值需要getter方法
public Dept getDept() {
        return dept;
    }
  • xml配置文件
<bean id="emp" class="com.github.entity.Emp">
        <property name="name" value="zhangsan"></property>
        <property name="age" value="20"></property>
        <property name="dept" ref="dept"></property>
        <property name="dept.dname" value="技术部"></property>
    </bean>

    <bean id="dept" class="com.github.entity.Dept">
    </bean>
3.2.8 注入集合属性
  • 注入数组类型属性
  • 注入List集合类型属性
  • 注入Set集合类型属性
  • 注入Map集合类型属性
package com.github.entity;

import java.awt.*;
import java.util.*;
import java.util.List;

public class CollcetionSum {

    private String[] string;

    private List<String> list;

    private Set<String> set;

    private Map<String,String> map;

    public void setString(String[] string) {
        this.string = string;
    }

    public void setList(List list) {
        this.list = list;
    }

    public void setSet(Set set) {
        this.set = set;
    }

    public void setMap(Map map) {
        this.map = map;
    }

    @Override
    public String toString() {
        return "CollcetionSum{" +
                "string=" + Arrays.toString(string) +
                ", list=" + list +
                ", set=" + set +
                ", map=" + map +
                '}';
    }
}

 <bean id="collectSum" class="com.github.entity.CollcetionSum">
        <property name="string">
            <array>
                <value>语文</value>
                <value>数学</value>
            </array>
        </property>
        <property name="list">
            <list>
                <value>张安</value>
                <value>李四</value>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="key1" value="value1"></entry>
                <entry key="key2" value="value2"></entry>
            </map>
        </property>
        <property name="set">
            <set>
                <value>123</value>
                <value>456</value>
            </set>
        </property>
    </bean>
</beans>
@Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans4.xml");
        CollcetionSum collcetionSum = context.getBean("collectSum",CollcetionSum.class);
        System.out.println(collcetionSum);
    }

在这里插入图片描述

  • 集合里面设置对象类型值
<bean id="dept" class="com.github.entity.Dept">
        <property name="dname" value="研发"></property>
    </bean>

    <bean id="listClass" class="com.github.entity.ListClass">
        <property name="list">
            <list>
                <ref bean="dept"></ref>
            </list>
        </property>
    </bean>
  • 把集合注入部分提取出来
  1. 添加名称util空间
<?xml version="1.0" encoding="UTF-8"?>
<!-- 
    添加名称空间
-->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
  1. 配置xml文件
<bean id="dept" class="com.github.entity.Dept">
        <property name="dname" value="研发"></property>
    </bean>

    <util:list id="deptlist">
        <ref bean="dept"></ref>
    </util:list>

    <bean id="listClass" class="com.github.entity.ListClass">
        <property name="list" ref="deptlist"></property>
    </bean>

3.3 FactoryBean

  • Spring有俩种类型bean,一种为普通bean,另一种为工厂bean(FactoryBean)
  • 普通bean:在配置文件中定义bean类型就是返回类型
  • 工厂bean:在配置文件中定义bean类型可以和返回类型不一样
3.3.1 如何实现
  • 创建类,让这个类作为工厂bean,实现接口FactoryBean
  • 实现接口里面的方法,在实现的方法中定义返回的bean类型
  • 创建类
public class MyBean implements FactoryBean<Dept> {
    @Override
    public Dept getObject() throws Exception {
        Dept dept = new Dept();
        dept.setDname("145");
        return dept;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

  • 配置xml
<bean id="mybean" class="com.github.entity.MyBean"> </bean>
  • 编写测试类
public void test2(){

        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Dept dept = context.getBean("mybean",Dept.class);
        System.out.println(dept);
    }

4.xml自动装配

4.1 什么是自动装配

  • 根据指定装配规则,Spring自动将匹配的属性值进行注入

4.2 自动装配过程

  • bean标签的autowire属性,配置自动装配

1.byName:根据属性名称注入
2. byType:根据属性类型注入

  • xml配置文件
<bean id="emp" class="com.github.entity.Emp" autowire="byType">
    </bean>

    <bean id="dept" class="com.github.entity.Dept">
    </bean>
<bean id="emp" class="com.github.entity.Emp" autowire="byName">
    </bean>

    <bean id="dept" class="com.github.entity.Dept">
    </bean>

5.引入外部资源文件

  • 引入context名称空间
  • 配置文件
<context:property-placeholder location="classpath:djbc.properties"></context:property-placeholder>
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值