揭秘Spring框架的核心:掌握IOC与DI实现松耦合与灵活性

在现代软件开发中,Spring框架以其强大的控制反转(IoC)和依赖注入(DI)特性而闻名。本文将深入探讨这两个概念,帮助你理解如何通过Spring实现松耦合,提升代码的灵活性和可维护性。

什么是控制反转(IoC)

控制反转(Inversion of Control,IoC)是Spring框架的核心思想之一。其核心目的是通过将对象的创建和管理交由Spring框架来实现对象之间的解耦关系。IoC的两大要素为:

  1. 控制:指的是对象创建和管理的权力。
  2. 反转:将创建和管理的控制权交给外部环境(如Spring IoC容器)。

硬编码解耦示例

在没有IoC之前,开发者通常需要硬编码来创建对象。下面是一个使用反射技术连接数据库的传统方式:

// 创建工具类
Properties properties = new Properties();
InputStream resourceAsStream = Test01.class.getClassLoader().getResourceAsStream("jdbc.properties");
properties.load(resourceAsStream);
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String name = properties.getProperty("name");
String pwd = properties.getProperty("pwd");

// 获取连接
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, name, pwd);
System.out.println(connection);

Spring IoC的实现步骤

  1. 定义需要解耦的类
  2. 将类注入到Spring容器:
    <bean id="唯一标识" class=""></bean>
    
  3. 从Spring容器中获取对象
    • 加载配置文件:
      ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
      
    • 获取对象:
      Student stu = (Student) context.getBean("stu");
      

IoC容器的类型

  • BeanFactory(父)
  • ApplicationContext(子)

常见的容器实现有:

  • ClassPathXmlApplicationContext:通过加载主配置文件的相对路径获取Spring容器。
  • FileSystemXmlApplicationContext:通过加载主配置文件的绝对路径获取Spring容器。
  • AnnotationConfigApplicationContext:加载配置类获取Spring容器。

什么是依赖注入(DI)

依赖注入(Dependency Injection,DI)是实现控制反转的关键技术,主要通过将Bean之间的依赖关系通过构造方法或setter方法注入,降低了组件之间的耦合度。

DI的实现方式

  1. set注入:
  • 将需要注入的对象属性生成set方法
  • 在xml中配置 <property name="bean的id" ref="引用其他bean对象id" value="值" />
<!--========set注入对象===========-->
    <bean id="controller" class="com.yk.controller.UserControllerImpl">
        <property name="service" ref="service"/>
    </bean>
    <bean id="service" class="com.yk.service.UserServiceImpl">
        <property name="dao" ref="dao"/>
    </bean>
    <bean id="dao" class="com.yk.dao.UserDaoImpl"/>

<!--========set注入基本类型==========-->
    <bean id="student" class="com.yk.pojo.Student">
        <property name="name" value="大白"/>
        <property name="age" value="12"/>
     </bean>

<!--==========set注入复杂类型=========-->
    <bean id="teacher" class="com.yk.pojo.Teacher">
        <property name="myList">
            <list>
                <value>晓晓</value>
                <value>小陆</value>
                <value>王强</value>
                <value>马猴</value>
            </list>
        </property>

        <property name="myArray">
            <array>
                <value>高伟</value>
                <value>刘思琪</value>
                <value>小黑</value>
                <value>朱红</value>
            </array>
        </property>

        <property name="mySet">
            <set>
                <value>苏州</value>
                <value>杭州</value>
                <value>南京</value>
                <value>西塘</value>
            </set>
        </property>

        <property name="myMap">
            <map>
                <entry key="访客" value="迷彩"/>
                <entry key="钥匙" value="房子"/>
            </map>
        </property>

        <property name="myPop">
            <props >
                <prop key="日本">樱花</prop>
                <prop key="中国">牡丹</prop>
            </props>
        </property>
    </bean>
  1. 构造注入:

    • 将需要注入的对象属性生成有参无参构造方法

    • 进行配置 <constructor-arg name="对象名" type="对象类型" index="下标" value="值" ref="引用其他bean对象">

  • 构造注入不支持注入复杂类型

<!--基本类型-->
<bean id="student1" class="com.yk.pojo.Student">
    <constructor-arg name="name" value="小天"/>
    <constructor-arg name="age" value="21"/>
</bean>
<bean id="student2" class="com.yk.pojo.Student">
    <constructor-arg type="java.lang.String" value="叶故"/>
    <constructor-arg type="java.lang.String" value="22"/>
</bean>

<bean id="student3" class="com.yk.pojo.Student">
    <constructor-arg index="0" value="明月"/>
    <constructor-arg index="1" value="18"/>
</bean>
<!--构造注入对象-->
<bean id="controller1" class="com.yk.controller.UserControllerImpl">
    <constructor-arg name="service" ref="service1"/>
</bean>
<bean id="service1" class="com.yk.service.UserServiceImpl">
    <constructor-arg name="dao" ref="dao1"/>
</bean>
<bean id="dao1" class="com.yk.dao.UserDaoImpl"/>

IOC容器对bean的管理

Spring IoC容器对Bean的管理

1. Bean的实例化

1.1 通过构造方法(默认方式)

在Spring中,最常见的Bean实例化方式是通过构造方法。例如,下面的配置创建了一个Student对象:

<!-- 使用构造方法进行Bean实例化 -->
<bean id="student" class="pojo.Student"></bean>

1.2 通过工厂方法

你可以创建一个工厂类来返回Student对象。以下是实现示例:

public class BeansFactory {
    public Student createStu() {
        System.out.println("执行普通工厂方法");
        return new Student();
    }
}

在XML文件中,使用以下配置:

<!-- 使用工厂方法进行Bean实例化 -->
<bean id="student" class="pojo.Student" factory-bean="factory" factory-method="createStu"/>
<bean id="factory" class="factory.BeansFactory"/>

1.3 静态工厂方法

Spring也支持静态工厂方法来实例化Bean,示例如下:

<!-- 使用静态工厂方法进行Bean实例化 -->
<bean id="student" class="factory.StaticBeansFactory" factory-method="createStudent"/>

2. Bean的作用域

Bean的作用域决定了Spring如何创建和管理JavaBean实例,以下是常用的作用域配置:

<!-- Bean的作用域配置 -->
<!-- 单例(默认) -->
<bean id="teacher1" class="pojo.Teacher" scope="singleton"/>

<!-- 多例 -->
<bean id="teacher2" class="pojo.Teacher" scope="prototype"/>

可用的作用域属性:

  • singleton:单例(默认)。
  • prototype:多例。
  • request:每个请求创建一个。
  • session:每个会话创建一个。

3. Bean的生命周期

Bean的生命周期管理涉及多个重要步骤,以下是主要阶段:

  1. 实例化
  2. 属性赋值(DI)
  3. 初始化
    • 通过接口 InitializingBean
    • 通过属性 init-method=""
  4. 使用
  5. 销毁
    • 通过接口 DisposableBean
    • 通过属性 destroy-method=""

示例实体类:

package pojo;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class User implements InitializingBean, DisposableBean {
    private String uname;

    public User() {
        System.out.println("1. 实例化");
    }

    public void setUname(String uname) {
        System.out.println("2. 属性赋值");
        this.uname = uname;
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("3. Bean对象的初始化 --> 接口");
    }

    public void doInit() {
        System.out.println("3. Bean对象的初始化 --> 属性");
    }

    @Override
    public void destroy() {
        System.out.println("5. Bean对象的销毁 --> 接口");
    }

    public void dest() {
        System.out.println("5. Bean对象的销毁 --> 属性");
    }
}

XML配置:

<!-- Bean的生命周期管理 -->
<bean id="user" class="pojo.User" init-method="doInit" destroy-method="dest">
    <property name="uname" value="大宝"/>
</bean>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值