控制反转(ioc)是将对象控制权移交容器的设计原则,依赖注入(di)是其具体实现机制;di通过构造器、setter或字段注入依赖,而依赖查找则主动调用容器获取bean;接口编程与注解配置进一步强化ioc的松耦合与可维护性。

如果您在学习Spring或现代框架时遇到“控制反转”与“依赖注入”这两个术语,却难以区分其本质与边界,则可能是由于二者常被混用但实际存在抽象层级差异。以下是对其核心概念的分步定义与对应示例:
一、控制反转(IoC):控制权的移交原则
控制反转不是具体技术,而是一种设计原则,它将对象的创建、依赖获取、生命周期管理等控制权,从应用程序代码内部移交给外部容器统一调度。传统方式中,类A通过new B()主动创建所依赖的对象B,导致A与B强耦合;IoC模式下,A不再负责B的实例化,仅声明“我需要B”,由容器在运行时提供已准备好的B实例。
1、编写一个UserService类,其中包含一个UserDao类型的成员变量;
2、不使用new UserDao()在构造方法或方法体内初始化该变量;
3、将UserService和UserDao的定义交由Spring容器管理,例如通过@Service与@Repository注解标识;
4、容器启动时自动完成UserDao的实例化,并将其注入到UserService中。
二、依赖注入(DI):IoC的具体实现机制
依赖注入是控制反转思想落地的技术手段,指容器在对象创建后,通过构造函数、Setter方法或字段直接赋值等方式,将所依赖的对象“注入”目标组件内部。DI使类无需关心依赖如何产生,只专注自身业务逻辑,从而实现解耦与可测试性提升。
1、在UserService类中定义一个私有字段private UserDao userDao;;
2、添加带有@Autowired注解的Setter方法:public void setUserDao(UserDao userDao) { this.userDao = userDao; };
3、确保UserDao已被Spring容器识别为Bean(如标注@Component);
4、容器检测到@Autowired后,自动查找匹配类型的Bean并调用该Setter完成赋值。
三、依赖查找(Dependency Lookup):IoC的另一种实现方式
依赖查找是IoC的非主流实现路径,指组件主动向容器发起查询以获取所需依赖,而非等待容器推送。这种方式削弱了被动性,增加了组件对容器API的依赖,因此在Spring中较少推荐,但在某些遗留系统或OSGi环境中仍有应用。
1、在类中注入ApplicationContext引用,例如通过@Autowired private ApplicationContext context;;
2、在业务方法中调用context.getBean(UserDao.class)显式获取实例;
3、该调用会触发容器根据类型匹配返回已注册的UserDao Bean;
4、注意:此方式破坏了松耦合原则,应优先采用依赖注入而非依赖查找。
四、接口驱动下的IoC体现
当系统基于接口编程时,IoC的价值尤为显著。接口定义契约,多个实现类可互换,而容器依据配置或注解决定注入哪一个具体实现,无需修改调用方代码。这使得替换日志组件、数据源、缓存策略等成为配置级操作。
1、定义接口NotificationService及其实现类EmailNotificationService和SmsNotificationService;
2、在业务类中声明private NotificationService notificationService;;
3、在配置类中使用@Bean方法返回new SmsNotificationService();
4、容器将该实例注入所有声明NotificationService依赖的位置,切换实现只需修改@Bean方法的返回值,不触及任何业务类。
五、XML配置与注解配置的IoC表达
IoC的配置方式影响开发体验与可维护性。早期Spring依赖XML文件声明Bean及其依赖关系;现代开发则普遍采用注解驱动,由容器扫描类路径自动注册与装配,大幅减少样板配置。
1、创建applicationContext.xml文件,在其中使用<bean id="userService" class="com.example.UserService"></bean>定义Bean;
2、在该<bean></bean>内嵌套<property name="userDao" ref="userDao"></property>建立依赖;
3、同时定义另一个<bean id="userDao" class="com.example.UserDao"></bean>;
4、启动时加载该XML,容器按顺序实例化并注入,此时依赖关系完全由XML描述,与Java代码分离。










