分层解耦
三层架构分别是:
Controller:控制层,用来接收请求,响应数据
Service:业务层,用来进行逻辑处理
Dao:数据访问层,用来进行数据访问
三层架构的关系
三层架构的作用
请看以下代码:
Controller:
@RestController
public class EmpController {
@RequestMapping("/listEmp")
public Result list(){
//1. 加载并解析emp.xml
String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
//System.out.println(file);
List<Emp> empList = XmlParserUtils.parse(file, Emp.class);
//2. 对数据进行转换处理 - gender, job
empList.stream().forEach(emp -> {
//处理 gender 1: 男, 2: 女
String gender = emp.getGender();
if("1".equals(gender)){
emp.setGender("男");
}else if("2".equals(gender)){
emp.setGender("女");
}
//处理job - 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 Result.success(empList);
}
}
统一返回结果类:
public class Result {
private Integer code ;//1 成功 , 0 失败
private String msg; //提示信息
private Object data; //数据 date
public Result() {
}
public Result(Integer code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public static Result success(Object data){
return new Result(1, "success", data);
}
public static Result success(){
return new Result(1, "success", null);
}
public static Result error(String msg){
return new Result(0, msg, null);
}
}
我们可以看到,上面的代码是不分架构的,控制层,业务层,数据访问层都在Controller
中写,这样会造成整个代码很乱,而且不利于维护,复用性差。
但是如果我们把他们分开写,利用面向接口编程的思想。
分别把三项功能封装在Controller
,Service
,和Dao
层中,我们就可以提高代码的复用性,便于后期维护,也会有利于扩展。
那么我们就可以构建以下思路:
Service
层接口:
//业务逻辑接口(制定业务标准)
public interface EmpService {
//获取员工列表
public List<Emp> listEmp();
}
Dao
层接口:
//数据访问层接口(制定标准)
public interface EmpDao {
//获取员工列表数据
public List<Emp> listEmp();
}
解耦
当我们要把EmpServiceA
切换到EmpServiceB
时,我们只需要
当service
层的代码发生改动,controller
层的代码也要跟着改动
我们就称controller
层和service
层耦合了.
问题来了,我们如何不修改对象就完成解耦的操作呢?
这里我们引入了IOC
容器(控制反转)和DI
(依赖注入)的概念
@Component
可以把Service
和Dao
层的实现类交给IOC
容器管理
Controller
运行需要依赖Service
对象,而Service
运行需要依赖Dao
对象,因此我们要加@Autowired
,这样我们就完成了依赖注入。
那么解耦我们是怎么实现的呢?
这里我创建了EmpServiceB
并做了以下红色改动:
把A中的@component
注释掉
也就是我只需要把B
交给容器管理,把A
从容器中拿出来即可
效果图如下:
IOC详解:
Bean的声明
Bean组件扫描
小结:
DI详解
Bean注入
当我们ServiceA
和ServiceB
同时放入容器中的时候,也就是两者的@Component
注解都打开,由于@Autowired
默认是按照类型
进行的,如果存在多个相同类型的bean
,就会出现以下报错。
小结: