IoC容器(控制反转和依赖注入)
为什么需要控制反转
为什么需要控制反转,new 是强依赖,new 是写死了
导致UserService
依赖于 UserDaoImpl
这个底层模块,违反了依赖倒置原则,同时如果更换实现类就违反了开闭原则
案例
class UserService{
public void getUser(){
// 直接依赖(强依赖)
UserDao userDao = new UserDaoImpl();
}
}
控制反转介绍
IoC全称Inversion of Control,直译为控制反转
IoC又称为依赖注入(DI:Dependency Injection)
依赖倒置是需求(原则),控制反转是接口,依赖注入是实现类
控制反转就是一种实现依赖倒置的一种有效手段(方法)
而依赖注入是对控制反转的具体实现
IoC容器是在容器(Bean容器)的扩展
IoC容器的核心职责是负责对象的管理以及对象之间的依赖
IoC容器 = IOC + 容器(Bean容器/容器工厂)
如果没有IoC只有容器,就不能实现 IoC
容器:人物 IoC:外挂
找到依赖的方式
主动(依赖查找)
从容器中拿,如果修改实现类只需要修改xml(配置文件)
不是控制反转,只是把创建放到容器中解决并没有把管理交给容器解决
UserService userService = context.getBean(UserDao.class);
被动(控制反转/依赖注入)
容器主动给
控制反转是完整把控制权(创建和管理[查找])交给Ioc容器解决
简单来说,我只管使用不管他是怎么来的(比喻:你只管下单,IoC容器管杀管埋)
专业来说,就是让容器自动将需要的 Bean
注入到相关的类中完成装配的过程
依赖的顺序
根据配置文件找到依赖,同时会根据依赖所依赖的去查找
<bean id="userDao" class="org.example.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="org.example.service.impl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao"/>
</bean>
<bean id="userController" class="org.example.controller.UserController">
<constructor-arg name="userService" ref="userService"/>
</bean>
实现IoC的两种方式
set方法
这样容器就会自动将bean通过set方法注入到UserService中
<bean id="userService" class="org.example.service.impl.UserServiceImpl">
<property name="对应的set方法去除set然后将下一个首字母改成小写的名称" ref="需要注入的bean的id"/>
</bean>
构造方法
这样容器就会自动将bean通过构造方法注入到UserService中
<bean id="userService" class="org.example.service.impl.UserServiceImpl">
<constructor-arg name="构造方法的参数名" ref="需要注入的bean的id"/>
</bean>
值注入
IoC容器可以注入Bean,那也可以注入值
如下是使用 set 方法注入,也可以使用构造方法
<bean id="userDao" class="org.example.dao.impl.UserDaoImpl">
<property name="string" value="值"/>
<property name="integer" value="123"/>
<property name="list">
<list>
<value>list1</value>
<value>list2</value>
</list>
</property>
<property name="set">
<set>
<value>set1</value>
<value>set2</value>
</set>
</property>
<property name="map">
<map>
<entry key="key" value="value"/>
</map>
</property>
</bean>
<bean id="userService" class="org.example.service.impl.UserServiceImpl">
<bean id="userDao" class="org.example.dao.impl.UserDaoImpl">
<constructor-arg name="string" value="值"/>
<constructor-arg name="integer" value="123"/>
<constructor-arg name="list">
<list>
<value>list1</value>
<value>list2</value>
</list>
</constructor-arg>
<constructor-arg name="set">
<set>
<value>set1</value>
<value>set2</value>
</set>
</constructor-arg>
<constructor-arg name="map">
<map>
<entry key="key" value="value"/>
</map>
</constructor-arg>
</bean>