spring boot 完整三层代码示例(Controller + Service + Repository)
采用标准分包结构,前后端分离风格,可直接新建 SpringBoot 项目运行
项目包结构
plaintext
com.eazy.demo
├── DemoApplication.java 启动类
├── controller
│ └── UserController.java
├── service
│ ├── UserService.java(接口)
│ └── impl
│ └── UserServiceImpl.java(业务实现)
├── repository
│ └── UserRepository.java
└── entity
└── User.java
1. 启动类 DemoApplication.java
java
运行
package com.eazy.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
2. 实体类 entity/User.java(数据库映射对象)
java
运行
package com.eazy.demo.entity; public class User { private Long id; private String name; private Integer age; // 无参构造 public User(){} // getter & setter public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
3. Repository 数据访问层 UserRepository.java
java
运行
package com.eazy.demo.repository; import com.eazy.demo.entity.User; import org.springframework.stereotype.Repository; // 数据访问层Bean @Repository public class UserRepository { // 模拟数据库查询 public User findUserById(Long userId){ User user = new User(); user.setId(userId); user.setName("张三"); user.setAge(22); return user; } }
4. Service 业务层
4.1 service/UserService.java 接口
java
运行
package com.eazy.demo.service; import com.eazy.demo.entity.User; public interface UserService { User getUserInfo(Long id); }
4.2 service/impl/UserServiceImpl.java 实现类
java
运行
package com.eazy.demo.service.impl; import com.eazy.demo.entity.User; import com.eazy.demo.repository.UserRepository; import com.eazy.demo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserServiceImpl implements UserService { // 注入Repository private final UserRepository userRepository; // 构造器注入(推荐写法) @Autowired public UserServiceImpl(UserRepository userRepository) { this.userRepository = userRepository; } @Override public User getUserInfo(Long id) { // 可以在这里增加业务校验、业务规则 if(id == null || id <= 0){ throw new RuntimeException("用户ID非法"); } return userRepository.findUserById(id); } }
5. Controller 控制层 UserController.java
java
运行
package com.eazy.demo.controller; import com.eazy.demo.entity.User; import com.eazy.demo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { private final UserService userService; @Autowired public UserController(UserService userService) { this.userService = userService; } @GetMapping("/user/info") public User getUser(@RequestParam Long id){ // 调用业务层 return userService.getUserInfo(id); } }
访问测试
启动项目,浏览器打开:
http://localhost:8080/user/info?id=1返回 JSON:
json
{ "id": 1, "name": "张三", "age": 22 }
流程链路(对应你学习的分层图)
请求 → UserController(Bean) →【依赖注入】→ UserService(Bean) →【依赖注入】→ UserRepository(Bean)
重点复盘
- controller、service、repository 全部是 Spring Bean,被容器扫描管理
- 层与层之间不手动 new 对象,全部依靠依赖注入
- 职责分离:
- Controller:接收请求、响应数据
- Service:业务逻辑、参数校验
- Repository:只负责数据查询
拓展说明:现在这里 Repository 是模拟数据;真实项目会替换成 Mybatis/JPA,SQL 写在 Repository 层,Service 不直接操作数据库。
在 Spring 中,当我们定义多个 Bean 时,部分 Bean 想要正常运行,需要依赖其他 Bean。Bean 装配(Bean wiring):在 Spring IOC 容器内部,把这些存在依赖关系的 Bean 互相关联起来的过程。如果手动管理依赖关系会非常复杂,因此 Spring 提供自动装配(Autowiring)来简化工作,也就是依赖注入 DI。左右两张图对比解读
左边:Spring Context without wiring(没有装配)
容器里仅仅存放了 3 个独立 Bean:VehicleControllerBean、VehicleServiceBean、VehicleRepositoryBean三个对象互相独立,没有任何关联!等同于:三个 Bean 都创建好了,但是 Controller 不知道去找 Service,Service 不知道去找 Repository。如果你不做装配,代码里想要调用,只能自己手动new或者自己从容器 getBean 互相赋值。右边:Spring Context with wiring & DI(开启装配 + 依赖注入)
Spring 自动建立联系:VehicleControllerBean → VehicleServiceBean → VehicleRepositoryBean也就是:Controller 内部自动注入 Service,Service 内部自动注入 Repository。👉 这就是我们 Demo 代码里@Autowired干的事情!和你刚才三层代码一一对应
plaintextVehicleControllerBean ← 对应 UserController VehicleServiceBean ← 对应 UserService VehicleRepositoryBean ← 对应 UserRepository链路完全一致:Controller 依赖 Service,Service 依赖 Repository,由 Spring 容器自动完成 Bean 之间的绑定。通俗一句话理解
Bean Wiring(Bean装配)装配 = 建立 Bean 和 Bean 之间的依赖关系实现装配最主流的手段就是 DI 依赖注入(@Autowired 自动装配)关键概念区分(别混淆)
- 注册 Bean:把 Controller、Service、Repository 创建出来,放进 Spring 容器(
@Service/@RestController/@Bean)- Bean 装配(Wiring):让 Controller 持有 Service、Service 持有 Repository,建立对象之间的引用关系(
@Autowired)先有 Bean,才能装配;只注册不装配,各个 Bean 互不认识,无法分层调用。三种注入方式:字段注入 /set 注入 / 构造器注入多个同类型 Bean 冲突解决方案:@Primary、@Qualifier@Autowired两种注入方式:
- 字段注入(Field):直接写在成员变量上
java运行@Autowired private UserService userService;
- setter 方法注入:注解写在 set 方法上
java运行@Autowired public void setUserService(UserService userService){ this.userService = userService; }
24. Autowiring Demo — Constructor Injection
构造器注入(官方推荐)java运行private final UserService userService; public DemoController(UserService userService){ this.userService = userService; }
SpringBoot 新版,构造器注入甚至可以省略@Autowired。


浙公网安备 33010602011771号