spring IOC容器 DI依赖注入
什么是IOC?什么是DI?
控制反转(IOC)是一种设计思想,并不是一种语言,依赖注入(DI)是实现IOC的一种方式。在不适用spring的程序中,我们通常是使用new来创建一个对象,对象的创建完全交由程序本身执行,代码耦合度较高。在使用IOC容器之后我们创建对象的的步骤交由IOC容器去做,我们只需使用配置文件或者注解给予容器一些需要的参数,然后我们需要用到的对象直接去容器中取出即可。
IOC创建对象的几种方式
首先编写一个实体类,用于下面例子使用
package com.demo1;
public class Test1 {
private String name;
private int age;
public Test1(){
}
public Test1(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Test1{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
1.使用无参构造方法(默认)
编写applicationContext.xml配置文件
其中一个bean标签即代表一个对象,这是IOC读取我们的配置文件默认使用类中的无参构造之后创建出来的;id:表示对象名;class:表示对象类型
property:这是我们的DI依赖注入,它的底层原理就是依赖于set方法,当程序没有set方法时将会报错,当字段未普通类型字段是也可以省略。
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="test1" class="com.demo1.Test1" >
<property name="name" value="李华" />
<property name="age" value="18" />
</bean>
</beans>
创建一个测试类来获取对象,并调用对象的方法:
import com.demo1.Test1;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void t1(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Test1 test1 = context.getBean("test1", Test1.class);
System.out.println(test1);
}
}
结果输出:
Test1{name='李华', age=18}
2.使用有参构造方法
将applicationContext.xml中的配置改为如下:
index:代表有参构造的参数列表的下表
当然这种也是使用set原理的注入方式
<bean id="test1" class="com.demo1.Test1" >
<constructor-arg index="0" value="李华" />
<constructor-arg index="1" value="18" />
</bean>
将applicationContext.xml中的配置改为如下:
name:表示参数名称
<bean id="test1" class="com.demo1.Test1" >
<constructor-arg name="name" value="李华" />
<constructor-arg name="age" value="18" />
</bean>
将applicationContext.xml中的配置改为如下:
type:参数的参数类型
<bean id="test1" class="com.demo1.Test1" >
<constructor-arg type="java.lang.String" value="李华" />
<constructor-arg type="int" value="18" />
</bean>
一些特殊类型的属性实现注入
我们通常会在实体类中使用一个集合或者对象等等,特殊类型属性在xml中如何配置?
我们先创建一个包含特殊属性的实体类:
package com.demo1;
import java.util.List;
import java.util.Map;
public class Test2 {
private Test1 test1;
private List<Object> list;
private Map<Object,Object> map;
public void setTest1(Test1 test1) {
this.test1 = test1;
}
public void setList(List<Object> list) {
this.list = list;
}
public void setMap(Map<Object, Object> map) {
this.map = map;
}
@Override
public String toString() {
return "Test2{" +
"test1=" + test1 +
", list=" + list +
", map=" + map +
'}';
}
}
现在,我们来配置xml文件,这里我们都采用无参构造的set原理注入,使用属性名字作为标识符。我们可以根据属性类型选择对应的标签,多尝试几次或者查看spring的学习文档。
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="test1" class="com.demo1.Test1" >
<constructor-arg type="java.lang.String" value="李华" />
<constructor-arg type="int" value="18" />
</bean>
<bean id="test2" class="com.demo1.Test2">
<property name="test1" ref="test1" />
<property name="list">
<list>
<value>星期一</value>
<value>星期二</value>
</list>
</property>
<property name="map">
<map>
<entry key="语文" value="90" />
<entry key="数学" value="100" />
</map>
</property>
</bean>
</beans>
测试类:
import com.demo1.Test1;
import com.demo1.Test2;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void t1(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Test2 test2 = context.getBean("test2", Test2.class);
System.out.println(test2);
}
}
结果:
Test2{test1=Test1{name='李华', age=18}, list=[星期一, 星期二], map={语文=90, 数学=100}}