一、优化分析
@RestController
public class DeptController {
private DeptServiceimpl Service = new DeptServiceimpl();
在之前的代码每一层在调取上一层的业务功能的时候都是new一个新对象出来之后再进行调取,但是这样的做法层与层之间的耦合太强,而且不利于代码的维护和扩展,本节基于面向接口编程和Springboot底层的IOC&DI对代码进行优化,分层解耦。
控制反转: Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转。
依赖注入: Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。
Bean对象:IOC容器中创建、管理的对象,称之为Bean。
二、优化具体实现
1. 将Dao 及 Service层的实现类,交给IOC容器管理
2. 为Controller 及 Service注入运行时所依赖的对象。
Spring IOC 容器通过注解(如 @Controller
、@Service
、@Repository
)自动扫描和注册组件,容器会自动创建这些组件的实例并管理它们的生命周期。
以下是项目中由 Spring 容器管理的类:
- Controller 层:
DeptController
- 使用
@RestController
注解,Spring 自动扫描并注册为控制器组件。
- 使用
- Service 层:
DeptServiceimpl
- 使用
@Service
注解,Spring 自动注册为服务组件。
- 使用
- DAO 层:
DeptDaoimpl
- 使用
@Repository
注解,Spring 自动注册为数据访问组件。
- 使用
Dao:
优化点:
使用了 @Repository
注解标记为 DAO 层组件,便于 Spring 管理。
将数据获取逻辑独立封装在 DAO 层,服务层只需要调用接口获取数据,而无需关心文件读取的 具体实现。
public interface DeptDao {
public List<String> get() throws IOException;
}
@Repository
public class DeptDaoimpl implements DeptDao {
public List<String> get() throws IOException {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("dept.txt");
List<String> lines = IOUtils.readLines(inputStream, "UTF-8");
return lines;
}
}
DeptService:
优化点:
依赖注入(DI):使用 @Autowired
注入了 DAO 层接口(DeptDao
),实现了对 DAO 层的解耦,
不再手动创建 DeptDaoimpl
对象。容器会将 DeptDaoimpl
的实例自动注入到 dao
属性。
public interface DeptService {
public List<Dept> list() throws Exception;
}
@Service
public class DeptServiceimpl implements DeptService {
@Autowired
private DeptDao dao;
public List<Dept> list() throws Exception {
List<String> lines = dao.get();
List<Dept> list = lines.stream().map(line -> {
String[] args = line.split(",");
int id = Integer.valueOf(args[0]);
String name = args[1];
LocalDateTime data = LocalDateTime.parse(args[2], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
return new Dept(id, name, data);
}).toList();
return list;
}
}
DeptController :
优化点:
使用了 @Autowired
注解,将 DeptService
接口注入,而不直接依赖具体实现类(如 DeptServiceimpl
)。
@RestController
public class DeptController {
@Autowired
private DeptService Service;
@GetMapping("/depts")
public Result list() throws Exception {
// src/main/resources/dept.txt
List<Dept> deptlist = Service.list();
return Result.success(deptlist);
}
}
三、扩展
声明bean的注解要想生效,需要被扫描到,启动类默认扫描当前包及其子包。
@Autowired注解,默认是按照类型进行,如果存在多个相同类型的bean,将会报错误
解决方案:
方案一:@Primary:
@Primary
@Component
public class DeptServiceImpl implements DeptService {
@Override
public List<String> queryDeptList() {
// 略……
}
}
方案二:@Qualifier:
@RestController
public class DeptController {
@Autowired
@Qualifier("deptServiceImpl")
private DeptService deptService;
}
方案三:@Resource:
@RestController
public class DeptController {
@Resource(name = "deptServiceImpl")
private DeptService deptService;
}
四、总结
通过优化后:
-
分层解耦:
- DAO、Service、Controller 三层通过接口实现解耦,层与层之间仅依赖接口而非具体实现。
-
使用注解简化开发:
@Autowired
:实现依赖注入,提升代码的可读性和扩展性。@Service
和@Repository
:明确组件职责,方便 Spring 容器管理。
-
可扩展性提升:
- 面向接口编程使得后续更换实现(如切换到数据库存储)变得简单。