什么是IOC设计思想?
IOC:Inversion of Control 一般被翻译为”控制反转“, 主要的目的就是达到解耦合的作用,解除了创建Java对象和 Java代码之间的耦合度(个人理解)
1、首先用传统开发模式写一段代码
首先新建一个UserDao接口
public interface UserDao {
void getUser() ;
}
创建UserDao 的实现类
public class UserDaoImpl implements UserDao {
public void getUser() {
System.out.println("UserDaoImpl层中的getUser方法执行");
}
}
新建一个UserService 接口
public interface UserService {
void getUser() ;
}
创建UserService 的实现类
public class UserServiceImpl implements UserService {
//创建dao层对象
private UserDao userDao = new UserDaoImpl();
@Test
public void getUser() {
//调用dao层实现类的方法
userDao . getUser(); //UserDaoImpl层中的getUser方法执行
}
}
此时由于项目需求的增加需要再增加一个UserDao 的实现类 为 UserDaoAddImpl ,我们继续为UserDao增加一个新的实现类
public class UserDaoAddImpl implements UserDao {
//创建dao层对象
public void getUser() {
//调用dao层实现类的方法
public void getUser() {
System.out.println("UserDao中的新增的getUser方法执行");
}
}
测试该新增的实现类,对应的UserService 层的代码也需要改变
public class UserServiceImpl implements UserService {
//创建dao层新实现的对象 !!!!!!!!!!
private UserDao userDao = new UserDaoAddImpl ();
@Test
public void getUser() {
//调用dao层实现类的方法
userDao . getUser(); // UserDao中的新增的getUser方法执行
}
}
此时项目需求又来了,又要增加一个实现类,或者再代码需求量非常大的场景下,这种每次都去修改源代码 重新获取 新对象的方式根本就是行不通的,因为每个Java对象之间的耦合度太高了,修改一个就会牵连其他的。
2、如何解决以上的对象之间耦合度高问题呢?
我们可以在需要使用到该对象的地方不是直接去创建该对象,而是对外提供一个公开的set 方法,让别人去创建,我们只需在set方法中设计一个 抽象的形参 去接受传入的新的实现对象即可。
public UserServieImpl implements Uservice {
//创建UserDao 的空引用
UserDao userDao = null;
//创建一个对外公开的set方法,形参设置为抽象UserDao接口,不用去管具体的实参实现
//具体传入那个实现类对象交给实现者即可
public void set(UserDao userDao) {
//将定义的实例变量赋上具体值
this.userDao = userDao;
}
public void getUser() {
userDao . getUser();
}
}
测试代码:
public void test() {
UserService userService = new UserServiceImpl();
//调用set方法传入具体需要创建的对象
userService .set(new UserDaoImpl());
//开始具体的调用即可
userService .getUser();
//此时又想去实现另一个实现类呢?
//只需再次调用set方法,传入新的需要实现的类即可
userService .set(new UserDaoAddImpl());
//开始具体调用新的实现类中的方法即可
userService .getUser();
}
以上的代码从 UserDao userDao = new UserDaoImpl( );---------> this.userDao = userDao;
其实程序已经从根本上发生了改变。
第一种:直接将对象的具体创建直接写死在了的Java代码中,后期项目需求变了又要重新修改Java代码的对象的新实现,Java对象的创建控制权在Java代码手里,所有的东西都是由程序去控制的,Java代码和对象的创建之间耦合度太高。
第二种:不去做具体的实现,而是设计一个公开的set方法去接收具体的实现,Java代码不用去管具体创建哪个对象,创建对象的控制权交给了调用者来控制(不一定是程序员),把主动权交给了调用者,程序员不用去管怎么创建对象了,只负责提供一个接口即可,达到了Java对象和Java代码之间的解耦合。
这种思想,从本质上解决了问题,程序员不用再去关心对象的创建,而是去关心具体业务的实现,耦合度大大降低,这就是IOC的原型。
其实,IOC控制反转的思想早在面向对象中就有了体现,面向对象中的 “封装” 将属性私有化,只对外提供一个set方法来完成属性的修改,而不是直接给属性赋指定的值,而是根据传入的实参去赋值,具体的传入值交给调用者,实体类只负责提供一个接口即可。
IOC(控制反转)是一个设计思想,DI(Dependency injection)依赖注入,只是实现IOC的一种方式。采用的是以注入依赖的形式来提供需要创建的对象。
什么是DI(依赖注入)
以上的程序中,在UserService 中创建了 UserDao 的具体对象,可以理解为 UserService 依赖于 UserDao ,而UserDao 是被依赖的,依赖注入就是:在UserService 中 注入 UserDao 被依赖者的对象,这就叫做依赖注入。
IOC是Spring 框架的核思想,DI(依赖注入)也是Spring框架实现IOC的方式,采用的是依赖注入,
程序员只需编写对应类的依赖文件,spring框架底层的 Spring IOC Container 控制容器 自动帮我们创建对象 注入给 指定的类。
Spring 框架 提供了多种方式 实现 DI (依赖注入),可以使用 XML 配置文件,也可以使用注解。
Spring 容器在初始化时先读取配置文件 applicationContext.xml , 根据配置文件或元数据创建与组织对象存入容器中,spring 的 IOC 容器自动帮我们创建和管理对象(采用了单例模式和工厂模式)程序使用时再从IOC容器中取出需要的对象。
采用XML的方式来配置Bean的时候,Bean的定义信息(配置文件)和实现(容器创建)是分离的,而采用注解的方式来配置可以把两者结合为一体,Bean的定义信息直接以注解的形式定义在实现类中,而达到零配置的目的。
Spring中的控制反转是一种通过描述(XML或注解)并通过第三方生成获取对象的方式。在spring中实现控制反转的是 IOC容器(IOC容器控制对象的创建),其实现的方法是 DI(依赖注入,程序员负责编写配置文件完成依赖注入)。