Spring框架中最经典的两个组件就是IOC和AOP,其中IOC(Inversion of Control)是什么呢?
1. 为什么需要 IoC
举个最简单的例子,三层架构的Web系统,Controller调用Service实现业务逻辑,Service层调用Dao层实现数据提取和持久化。
我们现在要实现一个接口:getUserList
public class UserController {
public UserController (){
serviceA = new serviceA(XX, XX, XX);
serviceB = new serviceB(XX, XX);
serviceC = new serviceC(XX, XX);
}
private ServiceA serviceA;
private ServiceB serviceB ;
private ServiceC serviceC;
public object getUserList() {
serviceA.xxx();
serviceB.xxx();
serviceC.xxx();
}
}
在上述代码中,我们的 ServiceA,ServiceB,ServiceC 三个对象是如何实例化的呢?
一种办法,我们可以实现一个 UserController 的构造函数,new 出来:
public UserController (){
serviceA = new ServiceA(XX, XX, XX);
serviceB = new ServiceB(XX, XX);
serviceC = new ServiceC();
}
如果 Service 不需要额外的参数,那还比较简单,直接 new 即可,例如 serviceC 。
如果需要传参数,我们还需要将所有参数对象都先 new 创建出来,然后依次传入进去,实现 Service 的创建,例如:ServiceA 和 ServiceB。
在实际的业务中,我们完全有可能不仅仅是需要创建 Dao 层的对象,还需要领域层,缓存层等等。
在复杂的情况下,手动创建对象体系就是一个灾难,导致我们的代码难易维护,层与层之间紧密耦合在一起,任何一个接口或者类的构造函数改变,都需要将所有引用的地方进行修改。。。
解决上述问题,一个很好的解决思想就是 IoC 。
2. IoC
IoC — Inversion of Control,即「控制反转 」。
IoC 思想的本质:进程内所有需要托管的类都注册到 IoC 容器,当需要创建某个类的实例时(比如:Controller 接到一个新的 Http 请求),IoC 检查该类的构造函数参数类型,并创建相应的类实例,传入到构造函数中,完成类实例的创建,这个过程是递归进行的,直到实例创建完成,或者某个需要的参数类型无法创建,终止创建过程。
还是用上面的例子来说,如果用 IoC 来进行改造,最终结果如下:
public class UserController {
public UserController (ServiceA serviceA,
ServiceB serviceB, ServiceC serviceC ){
serviceA = serviceA;
serviceB = serviceB;
serviceC = serviceC;
}
private ServiceA serviceA;
private ServiceB serviceB;
private ServiceC serviceC;
public object getUserList() {
serviceA.xxx();
serviceB.xxx();
serviceC.xxx();
}
}
通过比较发现,最大的不同就在于 「UserController 」的构造函数是如何实现Service 实例创建上面。
在引入 IoC 后,类的构造变得非常简洁,需要依赖什么类型,直接在构造函数中添加一个参数即可,这个过程在 IoC 当中叫做注入(当然也可以有其他方式,最常用的方式就是构造函数注入)。
-
注入
注入是 IoC 框架创建对象的过程,也叫依赖注入。常见的注入方式有:构造函数注入、属性注入,目前 Spring 都支持,比较推荐使用「构造函数注入」。 -
容器
容器是 IoC 框架用来存储类型+对象间依赖关系的部分。
传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是 松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
2. IoC 实现原理
反射——反射是IoC得以实现的核心技术。
通过前述,我们知道 IoC 思想的核心就在于类实例的创建和声明周期管理。无论 IoC 使用的是什么技术,追踪都是要创建一个类的实例,而最 根本的就是 通过反射的方式,实现实例的创建和参数的注入。