1、什么是DI和IOC
Spring有两个核心概念,一个是IOC (Inversion of Control) 控制反转,一个是DI(Dependency Injection)依赖注入。IOC是一种设计思想,指的是将创建对象的操作交给容器,DI则是实现IOC的一种技术手段
上面的解释可能太宽泛了,我们可以试着这样来理解:我们将项目中供应Bean的一方简称为供方,将使用Bean的一方简称为需方;供方通过@Component等注解或Xml文件提供生成Bean的材料和入口,需方通过@Autowired等注解引入Bean,Spring属于第三方在中间扮演着Bean工厂的角色,它从供方收集好Bean,然后给需方注入Bean,如果生成的Bean还依赖其他的Bean,则通过递归的方式循环这套流程,这就是依赖注入。开发者不需要关心Bean是如何生成的,因为整个生产过程全都移交给了Spring这个第三方,这就是控制反转
2、Spring 解决的问题
那么Spring解决了什么问题?我们可以看看下面这个场景
A类中有成员b,调用A类的funcA方法时也会调用成员b的funcB方法,而B类中有成员c,调用B类的funcB方法时也会调用成员c的funcC方法...
# bean对象
class A {
private B b;
public A(B b){
this.b = b;
}
void funcA(){
b.funcB();
}
}
class B {
private C c;
public B(C c){
this.c = c;
}
void funcB(){
c.funcC();
}
}
class C {
...
}
# 调用A类的funcA方法
...
C c = new C(d);
B b = new B(c);
A a = new A(b);
a.funcA();
如果我们想要调用A类中的funcA方法,就需要先新建好A对象,而A对象的构造方法依赖B对象,所以又得先新建好B对象,而B又依赖C,依次类推
可以看到如果嵌套的层数够多,这个初始化的过程就会变得非常复杂,手动new一个实体类的成本会无限增加,代码也会变越来越臃肿,当然我们可以选择在构造器内new对象来优化代码,只不过显式的new对象会增加类之间的耦合,如果B类的实现发生变化(例如构造方法的参数改变),A类也需要相应地修改
下面看看Spring的解决方法
# bean对象
@Component
class A {
@Autowired
private B b;
void funcA(){
b.funcB();
}
}
@Component
class B {
@Autowired
private C c;
void funcB(){
c.funcC();
}
}
@Component
class C {
...
}
# 调用A类的funcA方法
@Autowired
private A a;
{
a.funcA();
}
Spring通过反射生成A类对象a,然后在初始化时发现A类中的b成员也是注入的,找到b成员的供方,也就是被@Component修饰的B类,通过反射生成B类对象b,然后B类又找到成员c的供方,依次类推
Spring的处理方法和new对象的不同之处在于不需要我们手动初始化一大堆成员变量,Spring将生产Bean的过程从我们手中隐式的转移了到了工厂内,只需要我们定义好供需关系,就能很快创建出一个复杂的Bean,这有效降低了代码间的耦合
3、Spring源码相关内容
这期先分享下自己对Spring的理解,有空再做一个Spring源码的解析