很多刚学 Spring 的人,都会有一个疑问:

OrderService orderService = new OrderService();

这样写有什么问题?

对象不是创建出来了吗?

代码不是也能跑吗?

为什么 Spring 一定要:

@Autowired
private OrderService orderService;

很多文章会告诉你:

“这是为了降低耦合”

但其实:这个解释太浅了

因为:即使你自己 new, 照样也可以通过接口解耦

真正的问题,从来不是:

“能不能 new”

而是:

“谁来管理对象”

一、自己 new 最大的问题是什么?

先看一个最简单的例子:

public class OrderService {
    public void createOrder() {
        System.out.println("创建订单");
    }
}

使用:

OrderService orderService = new OrderService();
orderService.createOrder();

完全没问题,于是很多人会觉得:

Spring 好像只是帮我少写了一个 new

其实不是。因为:

一旦对象由你自己 new

Spring 就彻底失去了对它的控制

而这,才是问题的核心

二、Spring 真正想控制的是什么?

很多人理解 IOC:

控制反转 = 对象交给 Spring 创建

这只是表面

真正核心其实是:

“对象控制权”

更准确地说:

Spring IoC 容器

接管的是:

  • 对象创建
  • 对象装配
  • 生命周期管理

的控制权

包括:

  • 对象什么时候创建
  • 对象什么时候销毁
  • 对象依赖谁
  • 对象是否单例
  • 对象是否需要代理
  • 对象是否需要事务增强
  • 对象是否需要缓存增强

这些,都需要 Spring 接管

三、IOC 为什么叫“控制反转”?

这里有一个非常经典的设计思想:

好莱坞原则(Hollywood Principle)

Don’t call us, we’ll call you.

别找我们,我们找你(不要主动调用我们,我们会在合适的时候调用你)

什么意思?

传统开发:

new OrderService().createOrder();

是:

你主动控制对象

你决定:

  • 什么时候创建
  • 什么时候调用
  • 怎么依赖

而 Spring 的模式是:

框架接管对象

再在合适的时候主动调用你

例如:

  • HTTP 请求来了,Spring 调 Controller
  • 定时任务时间到了,Spring 调方法
  • Bean 初始化完成,Spring 调生命周期回调
  • 事务开启后,Spring 再调业务方法

这才是真正的:

“控制反转”

反转的,不是对象
而是:

“对象与调用流程的控制权”

四、为什么 Spring 一定要接管对象?

因为:

Spring 的很多能力

本质上都建立在:

## “对象可控”

这个前提上

比如:


1、事务

例如:

@Transactional
public void createOrder() {

}

很多人以为:

@Transactional 是 Java 语法能力

其实不是。

本质上:

Spring 在运行时,
偷偷给你创建了一个“代理对象”

真正执行的,
并不是你写的那个对象

而是:

代理对象
    -> 拦截方法
    -> 开启事务
    -> 调用原方法
    -> 提交事务

问题来了

如果对象是你自己 new 的:

OrderService service = new OrderService();

Spring 根本不知道这个对象存在

那它还怎么增强?事务自然失效

2、AOP

比如日志:

@Before
public void log() {

}

或者权限:

@PreAuthorize

这些能力,本质上也都依赖:

Spring 先接管对象

再生成代理对象。

如果你自己 new:

Spring 根本插不进来


3、依赖注入

例如:

@Service
public class OrderService {
    @Autowired
    private UserService userService;
}

为什么 userService 能自动注入?

因为:

Spring 在创建 OrderService 时

会主动帮你把依赖塞进去

如果你自己:

new OrderService();

那 Spring 根本没参与创建过程,自然不会注入

于是:

userService == null

五、很多人其实一直误解了 IOC

很多教程:一上来就说:

IOC 是为了解耦

这句话不能说错,但:

解耦只是结果

不是本质,真正本质其实是:

“框架接管对象生命周期”

只有这样:

Spring 才能:

  • 做事务
  • 做 AOP
  • 做缓存
  • 做权限
  • 做自动注入
  • 做扩展增强

六、为什么说 Spring 本质是一个“对象管理框架”?

很多人觉得:

Spring = Bean 工厂

其实这也太浅了,Spring 真正强大的地方是:

它不仅创建对象

更重要的是:

它管理对象的整个生命周期

包括:

  • 创建
  • 初始化
  • 注入依赖
  • 增强代理
  • 销毁

这也是为什么:
Spring 几乎所有核心能力, 最后都会回到:

Bean 生命周期

七、为什么大型框架都喜欢“接管对象”?

不仅 Spring,
你会发现:

  • Spring
  • Dubbo
  • MyBatis
  • Netty
  • Tomcat

这些框架都有一个共同点:

“框架控制对象”

为什么?

因为:

只有控制对象

框架才能控制行为

否则:

开发者随便 new

框架根本无法:

  • 插件化
  • 统一增强
  • 生命周期管理
  • 上下文管理

八、那是不是所有对象都不能自己 new?

当然不是,很多初学者容易走向另一个极端:

“是不是所有对象都必须交给 Spring?”

其实并不是

例如:

new User()
new ArrayList<>()
new HashMap<>()

这种普通数据对象, 完全可以自己创建

因为它们:

  • 不需要事务
  • 不需要 AOP
  • 不需要生命周期管理
  • 不需要依赖注入

Spring 真正需要接管的

通常是:

“承载业务逻辑的组件对象”

比如:

  • Service
  • Controller
  • Repository
  • Component

因为这些对象:

需要被框架增强和管理

所以:判断一个对象是否应该交给 Spring,核心不是:

“能不能 new”

而是:

“它是否需要被框架管理”

九、真正理解 IOC 后,你会发现:

Spring 最核心的思想,其实不是:

“帮你创建对象”

而是:

“拿走对象控制权”

Spring 从来不只是一个:

“对象工厂”

它真正厉害的地方是:

让整个应用中的对象

第一次变得“可管理”,这才是真正的:

Inversion Of Control(控制反转)


关于老潘:

持续拆 Spring、MySQL、Redis 底层原理,复盘真实线上问题。

一起把“会用”变成“看懂”。

如果有帮助,点个赞、收藏支持一下。

下一篇:IOC 真正反转的到底是什么?很多人第一步就理解错了

感兴趣可以关注,避免刷着刷着找不到。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐