Java Spring是什么

Spring是“框架”

IOC(控制反转)+DI(依赖注入)

控制反转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class OrderService {

private UserRepository userRepository;
private OrderRepository orderRepository;

public OrderService() {
this.userRepository = new UserRepository(); // 自己 new
this.orderRepository = new OrderRepository(); // 自己 new
}

public void createOrder() {
// 业务逻辑...
}
}

现在我们在OrderService 中 创建两个引用类型的变量:userRepository、orderRepository。

在构造函数中我们如果想初始化这两个变量,就需要自己去new UserRepository和OrderRepository类对应的各自对象。

这里就可以发现弊端:

  1. 需要自己new对象之后才能使用
  2. 这里的对象的类型被定死了,但是如果在开发实践中,我们用的是redis类型的数据库客户端对象,需要根据接受类型的不同调整不同的数据库,可能要转成mongo DB。那么写死的方式就不适应这种开发模式。让维护和扩展性变差。

那么在使用控制反转和依赖注入后就变成了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Service
public class OrderService {

private final UserRepository userRepository;
private final OrderRepository orderRepository;

// 构造器注入
public OrderService(UserRepository userRepository,
OrderRepository orderRepository) {
this.userRepository = userRepository;
this.orderRepository = orderRepository;
}

public void createOrder() {
// 业务逻辑...
}
}

注意我们使用了**@Service**的注解。

在搭配上:

1
2
3
4
5
6
7
8
9
10
@Repository
public class UserRepositoryImpl implements UserRepository {
// ...
}

@Repository
public class OrderRepositoryImpl implements OrderRepository {
// ...
}

可以看到我们在OrderService 类中没有对userRepository和orderRepository对象进行new,而是直接给构造器传入两个对象,并直接使用传入的对象。

那么谁来创建userRepository和orderRepository对象呢?就是Spring 容器(IoC Container)。

控制反转怎么起效

Spring 创建 Bean

当我们在类上写@Service注解的时候:

1
2
@Service
public class OrderService {}

那么在Spring启动的时候会完成:

  1. 扫描所有的注解:@Component、@Service、@Repository、@Controller
  2. 通过反射创建对象
  3. 将对象放进IoC的容器中,由容器进行统一管理
  4. 以后拿到手的所有OrderService 对象,都是来自Spring的容器。

由此:对象的生命周期全盘都由Spring接管。

Spring 注入依赖

刚才发现 UserRepository 和 OrderRepository 是两个接口。我们为接口创建了实现类。

但是在我们的构造器中,我们不需要再指定是哪个实现类的对象,只需要告诉构造器我们需要哪个类型的对象即可。

于是Spring:

  • 根据类型找到对应的实现类的 Bean(比如 UserRepositoryImpl
  • 帮你自动塞进构造函数里
  • 你完全不用管创建过程 & 绑定逻辑

也就意味着,我们不再需要主动去new,而是对象被Spring自动送入构造器中。

“回调点”

从此运行都由Spring框架进行掌握,我们只需要进行回调,例如:在Spring MVC中

1
2
3
4
5
6
7
@RestController
public class HelloController{
@GetMapping("/hello")
public String hello(){
return "Hi!";
}
}

在这段代码中并不是我们写了main(),然后再去调用hello()。

而是:由客户端发送Get请求 → 容器(Spring MVC + Tomcat)接管 → 找到对应的Controller → 调用 hello()方法。

程序的流程完全是由Spring控制的,我们只为它提供“插槽/回调”。

什么是回调

回调(Callback)= “我先把一段代码/函数交给你保存,以后由你在合适的时机再来调用我这段代码。”

举例:按钮点击监听

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
interface OnClickListener {
void onClick();
}

class Button {
private OnClickListener listener;

// 1) 我先把“要干啥”交给 Button
public void setOnClickListener(OnClickListener listener) {
this.listener = listener;
}

// 2) Button 什么时候“调用你的代码”,由它自己决定
public void click() {
if (listener != null) {
listener.onClick(); // ✅ 这里就是“回调”
}
}
}

执行方:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test {
public static void main(String[] args) {
Button button = new Button();

// 把一段逻辑(实现 OnClickListener)交给 button 保存
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick() {
System.out.println("按钮被点了,执行我的逻辑");
}
});

// 某个时刻:按钮被点击
button.click(); // 这里会触发上面的 onClick()
}
}

  • 从你视角:你没主动去调用 onClick,是 Button 帮你调用的
  • 从 Button 视角:它“在适当时机,调用了你之前交给它的代码”

回到我们的Spring中在Spring MVC里的Controller方法:

1
2
3
4
5
6
7
8
@RestController
public class HelloController {

@GetMapping("/hello")
public String hello() {
return "hi";
}
}
  • 你有没有在 main 里写 new HelloController().hello()?👉 没有
  • 谁来调用 hello()?👉 Spring MVC / Tomcat 在有 HTTP 请求 /hello 的时候调用
  • 你只负责:把“接到 /hello 请求时要干啥”这件事告诉框架
  • 什么时候调 / 调多少次 / 是否并发调,全由框架决定

所以 hello() 这个方法,本质上就是一个HTTP 请求到达时的回调方法

AOP(面向切面编程)

我们都知道Java是面向对象编程(OOP),而我们的Spring则是AOP,面向切面编程。

是把横切的逻辑抽出来,进行统一的管理。

比如:日志、安全、事务、监控

1
2
@Transactional
public void saveOrder() {}

Spring 会自动的加上begin、commit、rolback的逻辑,这些本来我们需要自己完善的逻辑被Spring统一注入了。

如此具体的saveOrder业务逻辑就会很干净,而且实现了非业务功能的隔离。

企业开发能力

Spring框架提供了一堆的模块,可以实现不同的功能

模块 能力
Spring Web (MVC) 写 Web、Controller、REST API
Spring JDBC / ORM 访问数据库
Spring Security 安全、鉴权
Spring Transaction 事务管理
Spring Test 单元测试支持
Spring Messaging 消息、队列支持
Spring Scheduler 定时任务

你要写企业应用,只要用 Spring 就够了,啥都有。