简单理解:
控制反转就是将代码的调用权(控制权)从调用方转移给被调用方(服务提供方)。
解释一下:
如果我们需要创建某个类,就需要程序员去修改代码,然后才可以得到想要的类。反转的意思就是不需要程序员去直接操作代码,而是通过服务方
(Spring)让框架的机制帮助程序员获得想要的对象,而程序员只需要修改配置文件,不用关心对象是怎么创建的。
举个例子:
1 public class UserServiceImpl implements UserService {
2 private UserDao userDao = new UserDaoImpl();
3 @Override
4 public void getUser() {
5 userDao.getUser();
6 }
7 }
如果 UserDao 接口被多个不同的类实现,那么在service层就要多次修改标蓝色的代码。
比如:增加一个 UserDaoMySqlImpl 类去实现 UserDao 接口
1 public class UserDaoMySqlImpl implements UserDao {
2 @Override
3 public void getUser() {
4 System.out.println("MySql获取用户数据");
5 }
6 }
那么如果在service层需要使用这个类,就要修改代码:
1 public class UserServiceImpl implements UserService {
2 private UserDao userDao = new UserDaoMySqlImpl();
3 @Override
4 public void getUser() {
5 userDao.getUser();
6 }
7 }
如果增加一千个类去实现这个接口,那么代码将被程序员修改一千次,这是很不合理的。
解决方法:
成员变量是UserDao接口类,但是并不去实现它,给一个实现的方法去实现。
1 public class UserServiceImpl implements UserService {
2 private UserDao userDao;
3 // 利用set实现
4 public void setUserDao(UserDao userDao) {
5 this.userDao = userDao;
6 }
7 @Override
8 public void getUser() {
9 userDao.getUser();
10 }
11 }
这样我们在调用不同的实现类的时候就可以这么写代码:
1 UserServiceImpl service = new UserServiceImpl();
2 service.setUserDao( new UserDaoOracleImpl() );
总结:
这也是一种反转,本身如果用户需要使用某一个服务类,需要程序员修改内部代码来实现,
现在程序员只需要给用户提供接口,用户根据需求填入参数就可以得到想要的类。
之前的主动权在程序,在程序员。
现在的主动权在调用者,就是调用 setUserDao( )方法的人,
程序成为了被动者。
这就是通过定义一个方法,以传参数的形式来返回一个类对象,而不用在类内部初始化另一个类,降低了代码的耦合性。
控制反转IoC(Inversion of Control),是一种设计思想,DI(Dependency Injection)依赖注入是实现IoC的一种方法。
反转
是程序和IoC容器的反转
之前如果程序想要获得某个对象,就直接自己主动去创建,主动权在程序。
有了IoC容器之后,
程序获取对象的主动权给了IoC容器,程序成为了被动的接收者,
只需要等待容器去创建对象并接收,不需要去主动修改代码获得对象。
Spring容器是如何实现的?
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。
在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
依赖:程序依赖IoC容器
注入:IoC容器帮助程序注入到某个对象需要的外部资源(比如给对象的变量赋值)