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)

重点复盘

  1. controller、service、repository 全部是 Spring Bean,被容器扫描管理
  2. 层与层之间不手动 new 对象,全部依靠依赖注入
  3. 职责分离:
    • Controller:接收请求、响应数据
    • Service:业务逻辑、参数校验
    • Repository:只负责数据查询
拓展说明:
 
现在这里 Repository 是模拟数据;真实项目会替换成 Mybatis/JPA,SQL 写在 Repository 层,Service 不直接操作数据库。
 
 
 
 
 
 
 
 

image

 

在 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 干的事情!

和你刚才三层代码一一对应

plaintext
 
 
VehicleControllerBean ← 对应 UserController
VehicleServiceBean    ← 对应 UserService
VehicleRepositoryBean ← 对应 UserRepository
 
链路完全一致:
 
Controller 依赖 Service,Service 依赖 Repository,由 Spring 容器自动完成 Bean 之间的绑定。

通俗一句话理解 Bean Wiring(Bean装配)

装配 = 建立 Bean 和 Bean 之间的依赖关系
 
实现装配最主流的手段就是 DI 依赖注入(@Autowired 自动装配)

关键概念区分(别混淆)

  1. 注册 Bean:把 Controller、Service、Repository 创建出来,放进 Spring 容器(@Service/@RestController/@Bean
  2. Bean 装配(Wiring):让 Controller 持有 Service、Service 持有 Repository,建立对象之间的引用关系(@Autowired
先有 Bean,才能装配;
 
只注册不装配,各个 Bean 互不认识,无法分层调用。
 
 
三种注入方式:字段注入 /set 注入 / 构造器注入
 
多个同类型 Bean 冲突解决方案:@Primary@Qualifier
 
@Autowired两种注入方式:
  1. 字段注入(Field):直接写在成员变量上
java
 
运行
 
 
@Autowired
private UserService userService;
 

 

  1. 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
posted @ 2026-07-22 21:32  漫漫长路</>  阅读(22)  评论(0)    收藏  举报