IOC(Inversion of controll 控制反转):对象之间的依赖关系由容器来控制。
DI(Dependency injection 依赖注入):容器通过调用对象提供的set方法或者构造器来建立依赖关系。
IOC是目标,DI是实现手段。
被注入类提供set方法,配置元素
以下给出一个简单的set方式注入依赖关系的例子:
1、配置xml文件
<bean id="b1" class="com.niuchen.spring.ioc.B"/>
<bean id="a1" class="com.niuchen.spring.ioc.A">
<property name="b" ref="b1"/>
bean>
2、定义类
// 注入类
public class B {
public B(){
System.out.println("B");
}
public void f1(){
System.out.println("B's f1");
}
}
// 被注入类
public class A {
private B b;//实际应用中更多使用接口定义对象属性,防止代码的修改,此处只为示例
public A(){
System.out.println("A");
}
// B类的set方法,注意方法名不可随意定义
public void setB(B b) {
System.out.println("setB");
this.b = b;
}
public void excute(){
System.out.println("excute");
// 注入依赖后在A类中直接调用B类方法
b.f1();
}
}
3、测试例
public class TestCase {
@Test
public void test3(){
AbstractApplicationContext ac = new ClassPathXmlApplicationContext("ioc.xml");
A a = ac.getBean("a1", A.class);
a.excute();
}
}
1.添加相应构造器
public class A {
//接口类型多态,避免了代码的修改
private IB b;
public A(){
System.out.println("A");
}
// 添加相应的构造器
public A(IB b){
System.out.println("A(B)");
this.b = b;
}
public void excute(){
System.out.println("excute");
b.f1();
}
}
2.配置constructor-arg元素
<bean id="b2" class="com.niuchen.spring.ioc2.B"/>
<bean id="a2" class="com.niuchen.spring.ioc2.A">
<constructor-arg index="0" ref="b2"/>
bean>
spring容器根据某种规则自动建立对象之间的依赖关系。
public class Waiter {
public Waiter(){
System.out.println("Waiter");
}
}
public class Restaurant {
private Waiter wt;
public Restaurant(){
System.out.println("Restaurant");
}
public void setWt(Waiter wt) {
System.out.println("setwt");
this.wt = wt;
}
@Override
public String toString() {
return "Restaurant{" +
"wt=" + wt +
'}';
}
}
配置xml
<bean id="wt" class="com.niuchen.spring.autoIn.Waiter"/>
<bean id="rest" class="com.niuchen.spring.autoIn.Restaurant" autowire="byName"/>
junit测试
@Test
// 自动装配
public void test5(){
AbstractApplicationContext ac = new ClassPathXmlApplicationContext("auto.xml");
Restaurant rest = ac.getBean("rest", Restaurant.class);
System.out.println(rest);
}
/**
*测试结果:Waiter
* Restaurant
* setwt
* Restaurant{wt=com.niuchen.spring.autoIn.Waiter@eafc191}
**/
配置property属性的value标签。
public class ValueBean {
private String name;
private int age;
public ValueBean(){System.out.println("Value");}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "ValueBean{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
<bean id="vb" class="com.niuchen.spring.value.ValueBean">
<property name="name" value="哈哈哈"/>
<property name="age" value="30"/>
bean>
set方式注入
与基本类型相似,只是配置文件不同,不同类型集合使用对应类型标签赋值,如List使用list标签,Set使用set标签。
<bean id="vb" class="com.niuchen.spring.value.ValueBean">
<property name="name" value="哈哈哈"/>
<property name="age" value="30"/>
<property name="city">
<list>
<value>北京value>
<value>重庆value>
<value>上海value>
list>
property>
<property name="interest">
<set>
<value>台球value>
<value>吉他value>
<value>音乐value>
set>
property>
<property name="score">
<map>
<entry key="英语" value="60" />
<entry key="数学" value="66"/>
map>
property>
<property name="db">
<props>
<prop key="usearname">ncprop>
<prop key="password">123456prop>
props>
property>
bean>
public class ValueBean {
private String name;
private int age;
private List<String> city;
private Set<String> interest;
private Map<String, Double> score;
private Properties db;
public ValueBean(){System.out.println("Value");}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setCity(List<String> city) {
this.city = city;
}
public void setInterest(Set<String> interest) {
this.interest = interest;
}
public void setScore(Map<String, Double> score) {
this.score = score;
}
public void setDb(Properties db) {
this.db = db;
}
@Override
public String toString() {
return "ValueBean{" +
"name='" + name + '\'' +
", age=" + age +
", city=" + city +
", interest=" + interest +
", score=" + score +
", db=" + db +
'}';
}
}
引用注入集合类型的值
对上个例子以引用方式注入的配置方式,该方式配置更整洁灵活,方便集合值重用
<util:list id="cityBean">
<value>北京value>
<value>重庆value>
<value>上海value>
util:list>
<util:set id="interestBean">
<value>台球value>
<value>吉他value>
<value>音乐value>
util:set>
<util:map id="scoreBean">
<entry key="英语" value="60" />
<entry key="数学" value="66"/>
util:map>
<util:properties id="dbBean">
<prop key="usearname">ncprop>
<prop key="password">123456prop>
util:properties>
<bean id="vb2" class="com.niuchen.spring.value.ValueBean">
<property name="city" ref="cityBean"/>
<property name="interest" ref="interestBean"/>
<property name="score" ref="scoreBean"/>
<property name="db" ref="dbBean"/>
bean>
附加小知识点:
spring表达式:#{bean_id.属性}
Spring容器可以通过Spring表达式获取到其他bean的属性值。
<bean id="sp1" class="com.niuchen.spring.value.SpelBean">
<property name="name" value="#{vb.name}"/>
<property name="city" value="#{vb.city[1]}"/>
<property name="score" value="#{vb.score.english}"/>
<property name="pageSize" value="#{config.pagesize}"/>
bean>