• (一)Spring启示录



    Spring学习目录

    下一篇:(二)Spring概述

    启示代码

    一个简单的业务需求:使用Mysql和MVC三层架构根据id删除用户
    dao层(持久层):
    创建接口:

    /**
     * 专门负责用户增删改查
     */
    public interface UserDao {
        /**
         * 根据id删除用户信息
         */
        void deleteById();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    创建接口的实现类:

    public class UserDaoImplMysql implements UserDao {
        @Override
        public void deleteById() {
            System.out.println("Mysql删除用户信息");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Service层(业务层):
    业务接口:

    /**
     * 业务层,处理业务逻辑
     */
    public interface UserService {
        /**
         * 删除用户信息
         */
        void deteleUser();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    业务层实现类:

    public class UserServiceImpl implements UserService {
        private UserDao userDao = new UserDaoImplMysql();
        @Override
        public void deteleUser() {
            userDao.deleteById();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    web层:

    
    public class UserAction {
        UserService userService = new UserServiceImpl();
        public void deleteRequest(){
            userService.deteleUser();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    测试程序:

    public class Test {
        public static void main(String[] args) {
            UserAction userAction = new UserAction();
            userAction.deleteRequest();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    请添加图片描述

    代码存在的问题

    如果用了一段时间后,客户改需求,想要用Oracle数据库,那么程序需要改动的地方

    • 1.dao层,提供一个Oracle实现类
    public class UserDaoImplOracle implements UserDao {
        @Override
        public void deleteById() {
            System.out.println("Oracle删除用户信息");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 2.service层,UserDao对象需要从new Mysql实现类改为new Oracle实现类
    private  UserDao userDao = new UserDaoImplOracle();
    
    • 1
    • 3.需要对之前的所有的程序进行测试

    违反OCP原则,DIP原则

    • OCP:开闭原则,对修改关闭(使用方),对扩展开放(提供方)。最重要、最核心、最基础的原则。
      软件需要变化时,尽量通过扩展软件实体行为来实现变化,而不是通过修改已有的代码来实现变化。
      当进行系统功能扩展的时候,如果修改了之前稳定的程序,那么之前所有的程序都要进行重新测试,这是非常麻烦的。

    • DIP:依赖倒转(倒置)原则,核心是面向接口编程

      • 1.高层模块不应该依赖底层模块,二者应该依赖其抽象。
      • 2.抽象不应该依赖–细节(指具体实现类),细节应该依赖–抽象(指接口和抽象类)。
        例如当前程序,从高层到低层 UserAction - UserServiceImpl - UserDaoImplMysql
        表示层UserAction 依赖了 业务层具体的的UserServiceImpl
        业务层的UserServiceImpl 又依赖了 持久层具体的的UserDaoImplMysql
        只要底层模块改变,高层必然受到牵连,所以违反了DIP原则,怎么遵守DIP,要面向接口编程,面向抽象编程,不要面向具体。

    引出IoC(控制反转)

    当前程序怎么让其遵守OCP和DIP原则,采用”控制反转“这种编程思想。
    控制反转:Ioc(Inversion of Control),是一种新型的设计模式,由于比较新,没有被纳入到GoF23种设计模式之中。
    控制反转的核心:

    • 其一:不采用硬编码方式new对象。
    • 其二:不采用硬编码的方式来维护对象的关系。

    控制反转的实现方式有多种,比较重要的是:依赖注入(Dependency Injection 简称DI)。

    • 依赖:A对象和B对象的关系。
    • 注入:通过手段让A与B产生关系(依赖)。

    DI有包括两种常见的方式:

    • 1.set注入(执行set方法给属性赋值)
    • 2.构造方法注入(执行构造方法给属性赋值)

    引出Spring框架

    首先,对当前程序进行改造
    1.service,UserDao不 new 具体的实现类了。
    2.UserAction也不new具体的service实现类。
    3.使用set注入或者构造方法注入

    service:

    public class UserServiceImpl implements UserService {
        //private UserDao userDao = new UserDaoImplMysql();
        //private  UserDao userDao = new UserDaoImplOracle();
        private  UserDao userDao;
    
        public UserServiceImpl(UserDao userDao) {
            this.userDao = userDao;
        }
    
        @Override
        public void deteleUser() {
            userDao.deleteById();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    web:

    public class UserAction {
        //UserService userService = new UserServiceImpl();
        UserService userService;
    
        public UserAction(UserService userService) {
            this.userService = userService;
        }
    
        public void deleteRequest(){
            userService.deteleUser();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    测试程序:

    public class Test {
        public static void main(String[] args) {
            //UserAction userAction = new UserAction();
            UserAction userAction = new UserAction(new UserServiceImpl(new UserDaoImplOracle()));
            userAction.deleteRequest();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    如果把这个Test看成一个Servlet,显然,具体需要用哪一个实现类,还是需要开发人员自己去new,如果这些实现类相当多,那么new的这个操作会相当复杂,可读性就会变差。
    我们可以使用Spring框架,让框架帮我们管理这些对象。
    Spring框架:Spring框架实现了控制反转Ioc这种思想的容器

    • 1.可以帮你new对象

    • 2.可以帮你维护对象之间的关系

  • 相关阅读:
    自学ansible笔记
    shell中实用eval命令和安全问题
    React路由
    github-将本地代码上传到github上
    Activiti 7 源码学习
    【reverse】新160个CrackMe之154-cpp_crackme1——MFC+纯算法逆向
    RK3568平台开发系列讲解(视频篇)摄像头采集视频的相关配置
    多项目管理的基本技巧有哪些?
    【mockserver】linux服务器搭建 easy-mock,用于挡板或模拟接口返回服务器
    C++-vector的代码实现(超详细)
  • 原文地址:https://blog.csdn.net/weixin_45832694/article/details/127808533