4.2 -Spring框架简单例子理解控制反转和依赖注入-xml配置版本

Spring 框架编程——控制反转(IoC,Inversion of Control)和依赖注入(DI,Dependency Injection)的基本用法

回到第一章:目录



前言

上一节,简单 介绍了 springboot 框架编写web应用程序,可见在sprinboot框架写编写web应用程序时多么便利。但要理解其编程方法还需要进一步学习。

这一节 通过一个简单的例子理解spring框架的核心概念 :控制反转(IoC,Inversion of Control)和依赖注入(DI,Dependency Injection)

简单例子理解控制反转和依赖注入

新建一个maven工程,pom文件中引入spring框架:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zhc</groupId>
    <artifactId>spring-1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
    </dependencies>
</project>

工程目录结构如下:
在这里插入图片描述

代码编写步骤

1、编写一个实体对象User。写好getter,setter,toString方法。

package com.zhc.domain;

/**
 * 第1步,编写一个实体对象。写好getter,setter,toString方法。
 */
public class User {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

2、在resource目录下新建配置文件:applicationContext.xml

 配置User对象 2个 到spring的容器中,scope="prototype" 告诉spring容器,User对象在需要时创建且可存在多个User对象的实列
 代码中使用id来获取spring容器中的对象,因此id不能重复。
 将创建的对象的任务交给spring框架来执行,而不是像平时通过new来执行。
 这种编程的思路可理解为:控制反转(IoC,Inversion of Control)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 第2步,配置User对象 2个 到spring的容器中,scope="prototype" 告诉spring容器,User对象在需要时创建且可存在多个User对象的实列
     代码中使用id来获取spring容器中的对象,因此id不能重复。
     将创建的对象的任务交给spring框架来执行,而不是像平时通过new来执行。
     这种编程的思路可理解为:控制反转(IoC,Inversion of Control)-->
    <bean id="user1" class="com.zhc.domain.User" scope="prototype">
        <property name="name" value="alis"></property>
        <property name="age" value="20"></property>
    </bean>
</beans>

3、创建UserDao接口和实现类UserDaoImpl,编写save方法,模拟持久层保存用户信息。

package com.zhc.dao.impl;

import com.zhc.dao.UserDao;
import com.zhc.domain.User;

/**
 * 第3步,创建UserDao接口和实现类UserDaoImpl,编写save方法,模拟保存用户信息。
 */
public class UserDaoImpl implements UserDao {
    public String save(User user){
        System.out.println("保存完毕:"+user.toString());
        return "保存成功";
    }
}

4、applicationContext.xml中增加配置 userDao 对象的信息

<!-- 第4步,配置 userDao 对象的信息到spring的容器中,scope="singleton" 告诉spring容器,userDao 在加载配置文件时就创建好,且只能存在1个。-->
<bean id="userDao" class="com.zhc.dao.impl.UserDaoImpl" scope="singleton"></bean>

5、编写 UserService 接口和他的实现类 UserServiceImpl

package com.zhc.service.impl;
import com.zhc.dao.UserDao;
import com.zhc.domain.User;
import com.zhc.service.UserService;

/**
 * 第 5 步,编写 UserService 接口和他的实现类 UserServiceImpl
 * 增加 UserDao 对象作为 UserServiceImpl 的属性用于操作保存用户信息;
 * save 是否能成功的业务代码逻辑应写在这里。
 * 这个 userDao对象,则是 UserService  的依赖。通常我们的写法是 UserDao userDao = new UserDao() 来创建对象。
 * 而现在使用spring框架,userDao对象不用自己new,而是从spring容器中根据id去取。
 * 下一步是在spring配置文件中配置bean,让spring根据配置文件自动创建 UserDao 对象。
 * 由于 UserDao 对象也配置,因此 UserService 在配置时,要把属性 userDao 也配置为从容器中获取对象实例。
 * 这个编程模式,可理解为:依赖注入(DI,Dependency Injection)
 */
public class UserServiceImpl implements UserService {

    private UserDao userDao;

    @Override
    public String save(User user) {
        // 写业务逻辑
        if(user.getName() == null){
            return "用户名不能为空";
        }
        if(user.getAge() < 0 || user.getAge() > 150){
            return "年龄输入不符合业务要求,应该输入 0-150之间的值。";
        }
        System.out.println("调用DAO层的userDao的save方法保存user对象。");
        return userDao.save(user);
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

6、applicationContext.xml中增加配置 userService 对象

<!-- 第6步,配置 userService 对象的信息到spring的容器中,scope="singleton" 告诉spring容器,userService 在加载配置文件时就创建好,且只能存在1个。
由于 userService 需要用到 userDao 来操作user的进行保存,即 userService依赖 userDao 。
因此将 userService 的属性 userDao 配置为从spring容器中获取:ref="userDao",这就是依赖注入的配置方法。-->
<bean id="userService" class="com.zhc.service.impl.UserServiceImpl">
    <property name="userDao" ref="userDao" ></property>
</bean>

7、编写 UserController 模拟发起用户信息的保存请求

package com.zhc.controller;

import com.zhc.domain.User;
import com.zhc.service.UserService;

/**
 * 第7步,编写 UserController 模拟发起用户信息的保存请求
 */
public class UserController {

    private UserService userService;

    public String save(User user){
        if(user == null){
            return "保存的user对象不能为空";
        }
        return userService.save(user);
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}

8、applicationContext.xml中增加配置 userController 对象

<!-- 第8步,配置 userController 对象的信息到spring的容器中,scope="singleton" 告诉spring容器,userController 在加载配置文件时就创建好,且只能存在1个。
同样,userController 用到了userService ,因此也需要配置依赖-->
<bean id="userController" class="com.zhc.controller.UserController">
    <property name="userService" ref="userService"></property>
</bean>

9、测试代码。

package com.zhc;

import com.zhc.controller.UserController;
import com.zhc.domain.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
    public static void main(String[] args) {
        /**
         * 第9步,测试。
         */
        // 加载spring配置文件,读取配置文件,将配置中的scope="singleton"(单例)bean标签,根据配置信息创建对象并放入spring容器中。
        ApplicationContext app  = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 调用 app 的  getBean( id )方法,通过id从spring容器中获取对象,得到的对象是Object,需要强制转换一下。
        UserController controller = (UserController) app.getBean("userController");

        // 从spring容器中获取 User 对象 user1,由于 User对象配置的是多例模式,scope="prototype",spring框架会在getBean()方法调用时创建User对象。
        User user = (User)app.getBean("user1");
        //调用 controller 的保存用户方法。
        String result = controller.save(user);
        System.out.println("用户:"+user + "的保存结果为:" + result );

        // 从spring容器中获取User对象 user2,由于 User对象配置的是多例模式,scope="prototype",spring框架会在getBean()方法调用时创建User对象。
        User user2 = (User)app.getBean("user2");
        //调用 controller 的保存用户方法。
        String result2 = controller.save(user);
        System.out.println("用户:"+user + "的保存结果为:" + result2 );

    }
}

10、小结

整个工程只有一个new关键字,那就是通过配置文件创建spring容器的上下文,
new ClassPathXmlApplicationContext(“applicationContext.xml”);
其他的对象创建工作全部交给了spring框架来管理。
这样做的好处是解耦合,比如 UserDao的实现修改了,变成NewUserDaoImpl.java,只需要改下配置文件,将 UserDaoImpl 改为 NewUserDaoImpl 即可。不需要修改 UserService 中的代码。
在这里插入图片描述

工程示例代码:
链接:https://pan.baidu.com/s/1A9QURA1FjxQXuKZf2nsiDQ
提取码:z26a

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值