没有 Spring 的时候我们怎么写代码先回忆一下远古时代的 Java 开发。假如你有个UserService里面要调UserDao去查数据库publicclassUserService{privateUserDaouserDaonewUserDao();// 自己 newpublicUsergetUserById(intid){returnuserDao.findById(id);}}看起来没毛病对吧问题在哪呢——UserService跟UserDao死死绑在一起了。哪天你要换一个UserDao的实现比如原本是 MySQL 版现在要换成带缓存的你就得去改UserService的代码。一个两个还好一个项目几百上千个类这么互相new那耦合度简直就是一坨缠绕的耳机线牵一发而动全身。这就是Spring IoC 要解决的问题。IoC 到底是什么IoC全称 Inversion of Control控制反转。名字很唬人其实就一句话创建对象的控制权不要攥在自己手里交给容器去管。没有 IoC 之前你自己new你说了算。有了 IoC 之后你告诉 Spring “我需要什么”Spring 帮你造好你要用的时候直接从容器里拿。翻译成人话以前你吃饭得自己去买菜洗菜切菜炒菜现在你只要把菜单丢给食堂等着端盘子就行。代码就变成了这样publicclassUserService{AutowiredprivateUserDaouserDao;// 不用 newSpring 帮你注入publicUsergetUserById(intid){returnuserDao.findById(id);}}UserService只管用不管建。谁建的Spring 建的。怎么进来的依赖注入进来的。DI 依赖注入IoC 的具体实现IoC 是一种思想DIDependency Injection是这个思想的具体实现方式。Spring 怎么知道UserService依赖了UserDao你告诉它的——通过注解或者配置文件。然后 Spring 在创建UserService的时候自动把UserDao注入进去。Spring 支持三种注入方式1. 字段注入最常用AutowiredprivateUserDaouserDao;最简洁写起来方便所以大家最爱用。贴个注解就完事了。底层原理不复杂Spring 通过反射拿到这个字段的Field对象然后调用field.set(bean, 依赖对象)直接给属性赋值。2. Setter 注入AutowiredpublicvoidsetUserDao(UserDaouserDao){this.userDaouserDao;}底层是通过反射获取 setter 方法的Method对象然后method.invoke(bean, 依赖对象)调用 setter 完成注入。3. 构造器注入AutowiredpublicUserService(UserDaouserDao){this.userDaouserDao;}底层是拿到有参构造器的Constructor对象然后constructor.newInstance(依赖1, 依赖2...)创建 Bean 的同时就把依赖注进去了。构造器注入目前是 Spring 官方推荐的方式。好处显而易见依赖在对象创建时就强制到位不会出现空指针而且对单元测试友好——你直接new UserService(mockDao)就能测不需要搞什么反射注入。Bean 到底是怎么造出来的反射是核心不管哪种注入方式底层都逃不开一个东西——反射。Spring 启动时的大概流程是这样的扫描扫包找到所有带Component、Service、Repository、Controller之类注解的类拿到全类名。反射创建实例Class.forName(全类名)加载类然后通过反射创建对象。检查生命周期注解如果方法上标了PostConstruct创建完 Bean 后执行标了PreDestroy销毁 Bean 前执行。依赖注入检查字段、setter 方法、构造器上的Autowired或Resource注解把依赖的 Bean 注入进去。放进容器Bean 创建好了、依赖也注入了放进 IoC 容器里本质就是一个大的 Map等着你用。整个过程反射从头忙到尾。工厂模式IoC 容器的外壳从设计模式的角度看IoC 容器就是一个超级工厂。普通的工厂模式一个工厂负责创建一类对象。Spring 的 IoC 容器负责创建、组装、管理应用中所有 Bean 的生命周期。你要用的时候不需要知道这个 Bean 是怎么来的ApplicationContextcontextnewClassPathXmlApplicationContext(applicationContext.xml);UserServiceuserServicecontext.getBean(UserService.class);或者现在更常见的直接Autowired注入AutowiredprivateUserServiceuserService;这就是工厂模式的威力——使用者不关心创建细节只管拿成品。总结串起来想一想整个 Spring IoC 的运转逻辑就是一条线你通过注解或 XML告诉 Spring 哪些类是 Bean、Bean 之间谁依赖谁Spring 启动时用反射扫描你的配置动态创建 Bean 实例根据依赖关系用反射把被依赖的 Bean 注入进去setter / 构造器 / 字段三种方式处理PostConstruct、PreDestroy等生命周期回调把创建好的 Bean 放进IoC 容器工厂模式的体现你需要用的时候从容器里取就行了理解了这一套Spring Boot 自动配置、条件装配那些高级特性本质上也是基于 IoC 容器做的扩展——万变不离其宗。我是小饼干如果这篇帮你理清了 IoC 和 DI点个赞吧。