三层架构和分层解耦
一、Java Web 三层架构
Java Web 应用可以大致分为三层:
- Controller 层(控制层)
- Service 层(业务逻辑层)
- Dao 层(数据访问层)
1. Controller 层
Controller 层主要负责接收前端发送的 HTTP 请求,并对请求进行处理后响应数据。
- 职责:
- 接收来自客户端(如浏览器、移动设备等)的 HTTP 请求(GET、POST、PUT、DELETE 等)。
- 解析请求中的参数(如查询字符串或表单数据)。
- 调用 Service 层的方法处理业务逻辑。
注:Controller 层不直接实现业务逻辑,而是通过调用 Service 层的方法来完成具体操作。
2. Service 层
Service 层负责实现具体的业务逻辑,是应用的核心部分。
- 职责:
- 实现复杂且核心的业务逻辑(例如银行系统中的转账业务)。
- 管理事务处理,确保多个数据库操作要么全部成功(提交事务),要么全部失败(回滚事务)。
- 为 Controller 层提供业务处理方法。
3. Dao 层
Dao 层(Data Access Object 层)主要负责数据访问和持久化操作。
- 职责:
- 将数据库操作封装为统一的接口,屏蔽具体数据库(如 MySQL、Oracle)及其底层细节。
- 执行数据的增删改查操作,例如调用
findUserById或saveUser方法。 - 实现数据的持久化,因而也被称为持久层。
插图展示


二、分层解耦
在软件开发中,高内聚低耦合是提高灵活性和可扩展性的关键设计思想。
- 内聚:模块内部功能的联系。
- 耦合:模块之间的依赖和关联程度。
在开发过程中,我们应尽量减少各层之间的依赖关系,实现解耦设计。
想要解耦,可以将一些对象放到容器中,在有容器去分配对象的使用
示例说明
以下内容以 Spring 框架为例,介绍如何通过控制反转(IoC)和依赖注入(DI)实现解耦。
三、控制反转(IoC)
在未使用 Spring 等框架前,对象之间的依赖通常由对象自己创建和管理,如下所示:
1 | public class BusinessLogicClass { |
这种方式会导致业务逻辑类与数据访问类紧密耦合,当数据访问层的实现发生变化时,业务逻辑类也需做相应修改。
控制反转(IoC) 的思想是将对象的创建和依赖关系管理交给外部容器(如 Spring 容器),由容器负责创建和管理对象(bean)。例如:
1 | public class BusinessLogicClass { |
在这个例子中,BusinessLogicClass 通过构造函数接收实现了 DataAccessInterface 的对象,从而只依赖于接口而非具体实现,达到了低耦合的目的。

1
2
3
4
5
6 // IOC将该类交给bean管理
public class UserServiceImpl implments UserService {
private UserDao userdap; // 加上了这个代表会自动去找bean中相应对象并实例化
}
- 注意@Component是加载实现类上而非接口上
IOC详解:
- 要把某个对象交给IOC容器管理,要在类上加上一下注解之一
- @Component : 声明bean的基础注解
- @Controller : 标注在控制层上
- @Service : 标注在业务层上
- @Repository :
bean的名字 : 默认是把你类名的首字母换成小写, 也可以在声明bean的时候声明名字,在注解后面打个括号后写入名字
IOC 的四大注解想要生效,必须具备组件扫描注解@ComponentScan扫描,这个注解没有显式h配置,但是在启动类的生命注解@SpringBootApplication中,默认的扫描范围是启动类所在的包和他的子包.
声明SpringBoot集成Web开发中,声明控制器bean只能用@Controller
四、依赖注入(DI)
依赖注入是指由容器在运行时将所需的依赖资源注入到对象中。Spring 框架支持多种依赖注入方式:
- 构造函数注入:在对象创建时通过构造函数传入依赖对象。(代码简洁但是隐藏了类的依赖关系)
- Setter 注入:通过 setter 方法注入依赖对象。 (如果只有一个构造函数@Autowired可以省略)
- 字段注入:直接在字段上使用注解(如
@Autowired)进行注入。
下面是字段注入的示例:
1 | import org.springframework.beans.factory.annotation.Autowired; |
有时候在一个包内注入了多个同类型的bean,此时会报错,解决方法 :
@Primary注解在多个可选的相同类型的 bean 存在时,告诉 Spring 容器优先选择带有@Primary注解的 bean 进行依赖注入。这避免了需要使用限定符(如@Qualifier注解)来指定所需的 bean。@Qualifier直接指定想要使用对应的bean的名字(记得名字是类名首字母小写或者是自己指定),@Resource(name = ""): 在name里面指定需要的bean的名字
Resource和Autowired的区别:
在IOC容器中创建,管理的对象就是Bean


五、解耦的好处
1. 可维护性
- 接口解耦:当某个模块的实现发生变化时,只需修改对应的实现类,不会影响其他模块。
- 例如:数据库从一种切换到另一种时,仅需调整数据访问层的实现和配置。
2. 可测试性
- 通过依赖注入,可以在单元测试中注入模拟对象(Mock 对象),隔离其他模块,专注于测试业务逻辑。
3. 可扩展性
- 新功能模块的集成只需在 Spring 配置文件中定义新的 bean,并通过依赖注入整合到系统中,实现灵活扩展。
以上内容详细阐述了 Java Web 的三层架构以及如何通过控制反转和依赖注入实现解耦设计,从而提升系统的可维护性、可测试性和可扩展性。