控制反转说明了Spring的一个特性,正常如果不用Spring,需要自己来创建对象进行实例化,而Spring的使用,让创建对象的过程变成了从Spring容器里注入,这样就把这种权利交给了Spring,控制反转可以简单地这么理解
对于Spring来实现属性依赖的注入,比如下面一个类
package com.lihuia.ioc;
/**
* Copyright (C), lihuia.com
* FileName: Demo
* Author: lihui
* Date: 2018/7/28
*/
public class Demo {
private Girl girl;
public void sayHello() {
System.out.println("Hello, " + girl.myGirl());
}
public void setGirl(Girl girl) {
this.girl = girl;
}
}
正常情况下,直接调用sayHello()方法,肯定会空指针,其中Girl类
package com.lihuia.ioc;
/**
* Copyright (C), lihuia.com
* FileName: Girl
* Author: lihui
* Date: 2018/7/28
*/
public class Girl {
public String myGirl() {
return "Lucy";
}
}
正常情况下的流程,应该是实例化一个Girl对象,传给setGirl方法,进而传递给Demo类的this.girl,最终sayHello()方法里this.girl才能调用myGirl()方法
用Spring注入,如果是通过setter方法来注入属性,XML如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="demo" class="com.lihuia.ioc.Demo">
<property name="girl" ref="girl"></property>
</bean>
<bean id="girl" class="com.lihuia.ioc.Girl"></bean>
</beans>
首先声明一个demo bean,接着最重要的就是property标签:
(1)这里决定了使用set$name($name第一个字母大写)方法
(2)ref的值必须是是该XML里id为girl的bean,将它作为参数传递到set$name($name第一个字母大写)中
还需要声明一个girl bean,类型是Girl,这样ref的值就表示set方法传入的对象是引用了这个bean
因此整个流程就变成girl这个bean赋给了set方法,传给了this.girl,最终调用其Girl类的成员方法打印输出
可以通过TestNG验证一下
package com.lihuia.ioc;
import javax.annotation.Resource;
import org.testng.annotations.Test;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
/**
* Copyright (C), lihuia.com
* FileName: DemoTest
* Author: lihui
* Date: 2018/7/28
*/
@ContextConfiguration(locations = {"classpath:ioc.xml"})
public class DemoTest extends AbstractTestNGSpringContextTests {
@Resource
private Demo demo;
@Test
public void testSayHello() {
demo.sayHello();
}
}
上面这个例子注入引用的是一个bean对象,更简单一点的是直接传一个值,那么property标签里对应的是value这个属性,比如
package com.lihuia.ioc;
/**
* Copyright (C), lihuia.com
* FileName: Demo
* Author: lihui
* Date: 2018/7/28
*/
public class Demo {
private String message;
public void sayHello() {
System.out.println("Hello, " + message);
}
public void setMessage(String message) {
this.message = message;
}
}
此时传入的是一个String类型的字符串,对于XML就更简单了
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="demo" class="com.lihuia.ioc.Demo">
<property name="message" value="Lucy"></property>
</bean>
</beans>
只需要一个demo bean,不需要在set方法里引用其他bean,而只需要传入一个具体的String类型的value即可,测试类和上面一样