IoC
控制反转IoC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IoC容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IoC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IoC容器了,通过IoC容器来建立它们之间的关系。
依赖注入和控制反转是从两个角度表达的同一个概念,前者从Spring角度,后者从调用者角度。 控制反转:当某个Java对象(调用者)需要调用另一个Java对象(被调用者,也就是被依赖对象)时,通常调用者会采用“new 被调用者”来创建对象,这样有一个痛点就是增强了调用者和被调用者之间的代码耦合,后期不好维护等等。所以在Spring框架中,对象的实例不再由调用者来创建了,而是由Spring容器来创建,控制权由我们写的代码(new 被调用者)转移到了Spring容器,这就是所谓的控制反转。
依赖注入
是从Spring角度看的,Spring容器负责将被依赖对象(被调用者)赋值给调用者,这相当于为调用者注入了它依赖的实例,这就是所谓的依赖注入。容器可以通过调用set方法或者构造器来建立对象之间的依赖关系。
set注入
场景:类A的execute方法需要类B的f1方法
public class B {
public B() {
System.out.println("B()");
}
public void f1() {
System.out.println("B's f1()");
}
}
类A中定义成员B变量,并添加set方法
public class A {
private B objb;
public A() {
System.out.println("A()");
}
//提供set方法
public void setObjb(B objb) {
this.objb = objb;
}
//该方法需要调用B的方法
public void execute() {
//new B().f1();!
System.out.println("execute()");
objb.f1();
}
}
配置bean,在配置文件中,set注入使用<property>元素来配置。name=属性名,ref=bean的id(引用)
<bean id="b1" class="ioc.B"/>
<!--属性名大写 setB acb=setAbc-->
<bean id="a1" class="ioc.A">
<property name="objb" ref="b1"/>
</bean>
启动容器输出结果:
B()
A()
setB()
execute()
B's f1()
构造器注入
public class B {
public B() {
System.out.println("B()");
}
public void f1() {
System.out.println("B's f1()");
}
}
/**
* 构造器注入
* @author Administrator
*
*/
public class A {
private B b;
public A() {
System.out.println("A()");
}
public A(B b) {
System.out.println("A(B b)");
this.b = b;
}
public void execute() {
System.out.println("execute()");
b.f1();
}
}
配置bean,使用bean的子元素<constructor-arg>来配置构造器注入
index属性:指定参数的下标(0为第一个)
ref属性:引用一个被注入bean的id
<bean name="b1" class="ioc2.B"/>
<!-- 构造器注入 -->
<!--
constructor-arg:容器会采用构造器来建立依赖关系
index:指定参数的下标
ref:被注入的bean的id
-->
<bean name="a1" class="ioc2.A">
<constructor-arg index="0" ref="b1"/>
</bean>
自动装配
注:自动装配,指的是容器依据某些规则,自动建立对象之间的依赖关系。
1)默认情况下,容器不会自动装配。 2)设置autowire属性
场景:类Restaurant需要注入类Waiter对象
/**
* 自动装配
* 服务员类
* @author Administrator
*
*/
public class Waiter {
public Waiter() {
System.out.println("Waiter()");
}
}
/**
* 自动装配
* 餐馆类
* @author Administrator
*
*/
public class Restaurant {
private Waiter waiter;
public Restaurant() {
System.out.println("Restaurant()");
}
//采用set方式注入
public void setWaiter(Waiter waiter) {
System.out.println("setWaiter(Waiter waiter)");
this.waiter = waiter;
}
@Override
public String toString() {
return "Restaurant [waiter=" + waiter + "]";
}
}
配置bean
<bean name="waiter1" class="ioc2.Waiter"/>
<bean name="waiter2" class="ioc2.Waiter"/>
<!--?↓
autowire属性:表示让容器自动建立对象之间的依赖关系
byName属性值:依据属性名查找对应的bean(以属性名作为bean的id来查找),
找到之后,调用set方法来建立依赖关系
注:如果找不到对应的bean则注入null;不可能找到多个符合条件的bean
byType属性值:容器依据属性的类型来查找对应的bean,找到之后,调用set()方法
来建立依赖关系
注:如果找不到对应的bean则注入null;可能如果找到多个bean,则会报错。
constructor属性值:容器依据属性的类型来查找对应的bean,
与byType类似,只不过,调用构造器来注入。
-->
<bean name="rest" class="ioc2.Restaurant" autowire="byType"/>