分层解耦
- 三层架构
- 分层解耦
-
- [IOC && DI](#IOC && DI)
- [IOC 详解](#IOC 详解)
- [bean 组件扫描](#bean 组件扫描)
- [DI | 依赖注入 详解](#DI | 依赖注入 详解)
-
- [@Primary 优先级](#@Primary 优先级)
- [@Quailfier 配合 @Autowired 指定注入哪个 bean](#@Quailfier 配合 @Autowired 指定注入哪个 bean)
- [@Resource 按照名称注入](#@Resource 按照名称注入)
- 依赖注入的注解
三层架构
① 接收请求、响应数据(Controller): 控制层,接收前端发送的请求,队请求进行处理,并响应数据
② 逻辑处理(Service): 业务逻辑层,处理具体的业务逻辑
③ 数据访问(Dao): 数据访问层(Data Access Object)(持久层),负责数据访问操作,包括数据的增、删、改、查
这样就能使我们的 类、接口,复杂性更低,逻辑性更强
Controller 层
只负责接收请求,响应数据
Service 层
只负责具体的逻辑处理,要获取数据,去调用 Dao
Dao 层
负责数据的访问操作
对比原先代码
java
package com.futao.controller;
import com.futao.pojo.Emp;
import com.futao.pojo.Request;
import com.futao.service.EmpService;
import com.futao.service.impl.EmpServiceA;
import com.futao.utils.XmlParserUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
@RequestMapping("/listEmp")
public Request<List<Emp>> list() {
// 1. 加载并解析emp.xml
String file = Objects.requireNonNull(this.getClass().getClassLoader().getResource("emp.xml")).getFile();
System.out.println(file);
List<Emp> empList = XmlParserUtils.parse(file, Emp.class);
// 2. 对数据进行转换处理
empList.forEach(emp -> {
// <!-- 1: 男, 2: 女 -->
String gender = emp.getGender();
if ("1".equals(gender)) {
emp.setGender("男");
} else if ("2".equals(gender)) {
emp.setGender("女");
}
// <!-- 1: 讲师, 2: 班主任 , 3: 就业指导 -->
String job = emp.getJob();
if ("1".equals(job)) {
emp.setJob("讲师");
} else if ("2".equals(job)) {
emp.setJob("班主任");
} else if ("3".equals(job)) {
emp.setJob("就业指导");
}
});
// 3. 响应数据
return Request.success(empList);
}
分层后
java
package com.futao.controller;
import com.futao.pojo.Emp;
import com.futao.pojo.Request;
import com.futao.service.EmpService;
import com.futao.service.impl.EmpServiceA;
import com.futao.utils.XmlParserUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
@RestController
public class EmpController {
private final EmpService empService = new EmpServiceA();
@RequestMapping("/listEmp")
public Request<List<Emp>> list() {
// 1. 调用service, 获取数据
List<Emp> empList = empService.listEmp();
// 2. 响应数据
return Request.success(empList);
}
}
分层解耦
IOC && DI
实现解耦操作,就不能使用 new 创建实例
将
Service & Dao
两个类交给IOC容器
管理
需要在类上面添加注解@Component
: 将当前类交给 IOC 容器管理,成为 IOC 容器中的 Bean
我们需要为 Controller & Service 运行时注入依赖的对象
在成员变量上加一个注解
@Autowired
:运行时,IOC 容器会提供该类型的 Bean 对象,并赋值给该变量
debug
IOC 详解
类似于这样
Controller层 就不用改动了,因为 @RestController 就包含了 @Controller 注解
bean 组件扫描
前面声明
bean
的四大注解,要想生效,还需要被组件扫描注解@ComponentScan
扫描。|
@ComponentScan
注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解@SprinqBootApplication
中,默认扫描的范围是启动类所在包及其子包
指定扫描哪个包(不推荐:@ComponentScan)
java
package com.futao;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan({"dao", "com.futao"})
@SpringBootApplication
public class SpringWebQuickstartApplication {
public static void main(String[] args) {
SpringApplication.run(SpringWebQuickstartApplication.class, args);
}
}
指定扫描哪个包(推荐)
按照 Springboot 项目的规范,将我们所写的代码,全部放在启动类所在包,及其子包下,这种结构 ↓
DI | 依赖注入 详解
当我们给 EmpServiceA 和 EmpServiceB 都添加一个 @Service 注解,再次启动会报错
@Primary 优先级
EmpServiceB 优先
@Quailfier 配合 @Autowired 指定注入哪个 bean
@Resource 按照名称注入
@Autowired 是按照类型进行注入的, 而 @Resource 是按照名称注入的
java
@Autowired
private EmpService empService;
注意,@Resource注解是由 JDK 提供的,而不是SpringBoot