1为什么要用Spring框架

2024-01-03 18:58:53

MVC初始结构图

dao-impl-UserDaoImpForMySQL
package com.sunsplanter.dao.impl;
import com.sunsplanter.dao.UserDao;
public class UserDaoImpForMySQL implements UserDao {

    @Override
    public void deleteById() {
        System.out.println("deleting User...");
    }
}
dao-UserDao
package com.sunsplanter.dao;
//yuyuemima wg9b
public interface UserDao {
    void deleteById();
}
service-Impl-UserServiceImp
package com.sunsplanter.service.impl;

import com.sunsplanter.dao.UserDao;
import com.sunsplanter.dao.impl.UserDaoImpForMySQL;
import com.sunsplanter.service.Userservice;

public class UserServiceImp implements Userservice {
    //控制层调用(操作)持久层,因此必须创造一个dao对象(控制具体的对象)
    //UserDao是抽象接口(框架),UserDaoImpForMySQL是实现类(实物),
    //new出一个实物,填进框架
   private UserDao userDao = new UserDaoImpForMySQL();
    @Override
    public void deleteUser() {
        //然后操作具体的userDao对象调用UserDao的方法
        userDao.deleteById();
    }
}
service-UserService
package com.sunsplanter.service;

public interface Userservice {
    void deleteUser();
}
web-UserAction
package com.sunsplanter.web;

import com.sunsplanter.service.Userservice;
import com.sunsplanter.service.impl.UserServiceImp;

public class UserAction {
    //表现层调用(操作)控制层,因此必须创造一个service对象(控制具体的对象)
    private Userservice userservice = new UserServiceImp();

    //如果有删除信息的需要,就调用表现层的deleteRequest方法,再套娃调用控制层的deleteUser方法
    public void deleteRequest(){
        userservice.deleteUser();
    }
}

client-Test
package com.sunsplanter.client;

import com.sunsplanter.web.UserAction;

public class Test {
    public static void main(String[] args) {
        //测试类,调用表现层去测试,因此先创造表现层对象
        UserAction userAction = new UserAction();

        userAction.deleteRequest();
    }
}

执行Test中的main方法,嵌套调用表现-控制-持久,最终输出deleting。。。

2

OCP开闭原则

然而,若持久层的代码发生了改变-例如从MySQL数据库更改为Oracle数据库,则dao-Impl中的实现类要重写,例如重写一个UserDaoImpForOracle,在这个新类中实现具体连接Oracle的代码.。

最糟的是,这还没完,由于三层架构是嵌套调用的关系,例如:在service-impl-UserService实现类中,有“ private UserDao userDao = new UserDaoImpForMySQL();”既然将dao层的实现类更改为了ForOracle,那么自然,控制层的实现类也要修改。

这样就违反了OCP开闭原则:对扩展开放,对修改关闭。
在上例中,如果因为修改持久层牵动控制层,那么后续要做的测试工作非常麻烦,甚至可能修改错。

DIP依赖倒置原则

在初始版本中,表现层必须new出控制层的对象才能操纵控制层,控制层又必须new出持久层对象。也即上层(表现层)依赖了下层(控制层)。
在这里插入图片描述

要满足该原则,以web-UserAction表现层实现类来说:

 //原本是这样,既然调用了控制层的实现类,那当然依赖于控制层
 private Userservice userservice = new UserServiceImp();
 //目标,不调用控制层实现类构造对象,但也能直接获取控制层的对象
  private Userservice userservice;

如果代码是这样编写的,才算是完全面向接口编程,才符合依赖倒置原则。
但是随之而来的一个问题是,这样userDao是null,在执行的时候就会出现空指针异常。而解决空指针异常的问题,其实就是解决两个核心的问题:
● 第一个问题:谁来负责对象的创建。【也就是说谁来:new UserDaoImplForOracle()/new UserDaoImplForMySQL()】
● 第二个问题:谁来负责把创建的对象赋到这个属性上。【也就是说谁来把上面创建的对象赋给userDao属性】
如果我们把以上两个核心问题解决了,就可以做到既符合OCP开闭原则,又符合依赖倒置原则。

Spring框架可以做到。

在Spring框架中,它可以帮助我们new对象,并且它还可以将new出来的对象赋到属性上。换句话说,Spring框架可以帮助我们创建对象,并且可以帮助我们维护对象和对象之间的关系。比如:

Spring可以new出来UserDaoImplForMySQL对象,也可以new出来UserDaoImplForOracle对象,并且还可以让new出来的dao对象和service对象产生关系(产生关系其实本质上就是给属性赋值)。
很显然,这种方式是将对象的创建权/管理权交出去了,不再使用硬编码的方式了。同时也把对象关系的管理权交出去了,也不再使用硬编码的方式了。像这种把对象的创建权交出去,把对象关系的管理权交出去,被称为控制反转。
在这里插入图片描述

IoC控制反转
…控制反转,是面向对象编程中的一种设计思想,可以用来降低代码之间的耦合度,符合依赖倒置原则。
控制反转的核心是:将对象的创建权交出去,将对象和对象之间关系的管理权交出去,由第三方容器来负责创建与维护。
…Spring应用了IoC:一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。换种说法,不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。

控制反转常见的实现方式:依赖注入(Dependency Injection,简称DI)
注入:让两个对象产生联系

通常,依赖注入的实现又包括两种方式:
● set方法注入

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

● 构造方法注入

public UserServiceImp(UserDao userDao) {
    this.userDao = userDao;
}

而Spring框架就是一个实现了IoC思想的框架。

 //原本是这样,既然调用了控制层的实现类,那当然依赖于控制层
 private Userservice userservice = new UserServiceImp();
 //目标,不调用控制层实现类构造对象,但也能直接获取控制层的对象
  private Userservice userservice;

Spring框架可以帮忙创建并管理UserServiceImp对象,每一个Spring框架创建并管理的对象,都称为一个Bean

文章来源:https://blog.csdn.net/m0_46671240/article/details/135367415
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。