Web后端开发中对三层架构解耦之控制反转与依赖注入

发布于:2024-05-07 ⋅ 阅读:(29) ⋅ 点赞:(0)

内聚与耦合

内聚 比如说我们刚刚书写的员工的实现类

在这里我们仅仅书写的是和员工相关的代码

而与员工无关的代码都没有放到这里

说明内聚程度较高

耦合

以后软件开发要高内聚 低耦合

提高程序灵活性 扩拓展性

分析代码

如何解耦

创建容器

提供一个容器 存储东西 存储EmpService类的实现

EmpController直接去容器中去找 又没有这个对象 复制给empService

有没有这个对象

控制反转与依赖注入

Springboot中很重要的概念

意思是如何操作运用容器

控制反转

是对象的创建控制权由应用程序转移到了外部容器 这个容器叫spring容器 ioc容器

依赖注入

是容器为应用程序提供运行时依赖的资源

Bean对象

表示IOC容器中创建管理的对象

IOC与DI的入门

控制反转和依赖注入的代码实现

我们需要完成controller层与service层的解耦

还有service层与dao层的解耦

具体代码程序

service层和dao层解耦 controller层和service层解耦

将两层中的对象删掉

程序会爆空指针异常

我们此时就需要用IOC和DI完成解耦操作

第一步 控制反转

第二步 需要ioc容器为其提供bean对象

启动springboot

部署后就可以访问服务端

如果以后我们在业务操作中要改变实现类

直接将需要交给控制层的核心逻辑层加上Component注释就行

再取消之前的实现类的注释

代表将当前实现类交给Bean容器管理

小结

控制反转:Component注解

将当前类交给IOC容器管理 成为IOC容器里的bean

依赖注入:Autowired注解

运行时,IOC容器会提供该类型的bean对象,并复制给该对象

代码实现

(只写了实现类)

package com.bigdate.threetier_architecture.dao.impl;

import com.bigdate.threetier_architecture.dao.EmpDao;
import com.bigdate.threetier_architecture.pojo.Emp;
import com.bigdate.threetier_architecture.util.XmlParserUtils;
import org.springframework.stereotype.Component;

import java.util.List;

//交给ioc容器处理 控制反转 称为ioc容器中的bean
@Component
public class EmpDaoA implements EmpDao {
    @Override
    public List<Emp> listEmp() {
        String file=this.getClass().getClassLoader().getResource("emp.xml").getFile();
        List<Emp>empList= XmlParserUtils.parse(file,Emp.class);
        return empList;
    }
}
package com.bigdate.threetier_architecture.service.impl;

import com.bigdate.threetier_architecture.dao.EmpDao;
import com.bigdate.threetier_architecture.dao.impl.EmpDaoA;
import com.bigdate.threetier_architecture.pojo.Emp;
import com.bigdate.threetier_architecture.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

//交给ioc容器处理 控制反转 称为ioc容器中的bean
@Component
public class EmpServiceA implements EmpService {

    @Autowired//程序在运行时 ioc会提供该类型的bean对象 并赋值给该对象 依赖注入
    private EmpDao empDao;
    @Override
    public List<Emp> listEmp() {
        List<Emp> empList=empDao.listEmp();
        empList.stream().forEach(emp -> {

            //处理gender
            String gender=emp.getGender();
            if(gender.equals("1")){
                emp.setGender("男");
            }else emp.setGender("女");

            //处理job
            String job=emp.getJob();
            if(job.equals("1")){
                emp.setJob("学生");
            }else emp.setJob("老师");



        });
        return empList;
    }
}
package com.bigdate.threetier_architecture.controller;

import com.bigdate.threetier_architecture.pojo.Emp;
import com.bigdate.threetier_architecture.pojo.Result;
import com.bigdate.threetier_architecture.service.EmpService;
import com.bigdate.threetier_architecture.service.impl.EmpServiceA;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class Controller {
    @Autowired//程序在运行时 ioc会提供该类型的bean对象 并赋值给该对象 依赖注入
    private EmpService empService;

    @RequestMapping("/listEmp")
    public Result list(){

        //调用service响应数据 再响应数据
        List<Emp> empList=empService.listEmp();

        //响应数据
        return Result.success(empList);

    }
}

IOC详解

概念

控制反转

将对象的容器交给IOC容器 由IOC容器创建管理这些对象

而IOC容器里这些对象又是bean对象

Component注解可以适用于一些工具类

实操

我们之前开发的后端架构其实就已经交给IOC容器管理

注解RestController

启动Springboot

Component的衍生注解 底层都封装了原注解和Component

bean容器默认是类名小写

Bean的声明

Bean的组件扫描

把数据层移出去 运行就会报错 因为找不到bean了

这里有个隐式注解

启动类当前包以及子包 搭建架构的常见错误

我们要加注解

这种解决方案不规范

我们在实际开发中应该按照springboot的规范来书写代码

启动类是放在总工程包下

而于启动类同级的是不同业务层的包 里面有接口和实现类

小结

DI详解

依赖注入

IOC容器要为运行程序提供需要的资源 资源即对象

自动装配

会去IOC容器中自动找这种类型的对象

然后赋值给对象

如果说往IOC容器里放入了两个同类型的对象

依赖注入时就会报错

解决

Primary注解

设置优先级

Autowired+Qualifier注解

指定bean的名字

如果说声明bean的时候默认没有设置

那就是类名小写

Resource注解

Autowired是按照类型注入的

而Resource是按照名称注入的

小结

面试题

@Resource@Autowired 是 Java 中用于依赖注入的注解,它们的主要区别如下:

  1. 来源:

    • @Resource 是 Java EE 提供的注解,在 javax.annotation 包中。
    • @Autowired 是 Spring Framework 提供的注解,在 org.springframework.beans.factory.annotation 包中。
  2. 用途:

    • @Resource 旨在通过名称进行依赖注入。它默认按照名称进行匹配,如果指定了 name 属性,则按照指定名称进行匹配。
    • @Autowired 旨在通过类型进行依赖注入。它默认按照类型进行匹配,如果多个匹配项,则会尝试按照名称进行匹配。
  3. 配置:

    • @Resource 可以通过 name 属性指定要注入的 Bean 的名称,也可以直接应用在字段、setter 方法或构造方法上。
    • @Autowired 可以应用在字段、构造方法、setter 方法上,通过类型匹配自动注入 Bean。
  4. 依赖性:

    • @Resource 是 Java EE 的标准注解,不依赖于 Spring,可以在非 Spring 容器中使用。
    • @Autowired 是 Spring 特有的注解,依赖于 Spring 框架,需要在 Spring 容器中才能生效。

总体而言,如果你想按照名称进行注入,可以使用 @Resource;如果你想按照类型进行注入,并且在 Spring 环境中使用,通常会选择 @Autowired