IOC控制反转和DI依赖注入:
http://blog.xiaohansong.com/2015/10/21/IoC-and-DI/
配置Bean其实就是使用DI依赖注入,将Bean交给IOC容器管理,实现IOC控制反转,达到解耦的过程。
Spring通过全类名(反射)配置Bean特点:
1. 基于xml文件的方式,
2. 通过全类名反射,
3. 依靠IOC容器,
4. 依赖注入的方式:属性注入,构造器注入
常见三种依赖注入:(下文先只介绍前两种)
1. 属性注入
2. 构造器注入
3. 工厂方法注入
Bean类:
package hello;
public class Hello {
String name;
int numberInt;
double numberDouble;
public void setName(String name) {
this.name = name;
}
public Hello() {
}
public Hello(String name, double numberDouble) {
this.name = name;
this.numberDouble = numberDouble;
}
public Hello(String name, int numberInt) {
this.name = name;
this.numberInt = numberInt;
}
@Override
public String toString() {
return "Hello{" +
"name='" + name + '\'' +
", numberInt=" + numberInt +
", numberDouble=" + numberDouble +
'}';
}
}
配置Bean的xml文件:
<bean id="helloIndex" class="hello.Hello">
<constructor-arg name="name" value="int类型" index="0">constructor-arg>
<constructor-arg name="numberInt" value="12" index="1">constructor-arg>
bean>
<bean id="helloInt" class="hello.Hello">
<constructor-arg name="name" value="int类型" index="0">constructor-arg>
<constructor-arg name="numberInt" value="12" type="java.lang.Integer">constructor-arg>
bean>
<bean id="helloDouble" class="hello.Hello">
<constructor-arg name="name" value="Double类型" index="0">constructor-arg>
<constructor-arg name="numberDouble" value="3.14" type="java.lang.Double">constructor-arg>
bean>
通过·setter·方法注入Bean的属性值或者依赖的对象,属性注入使用
元素.
使用name属性指定Bean的属性名称,value属性指定属性值。
id="helloSet" class="hello.Hello">
<property name="name" value="Spring">property>
可以使用p命名空间简化:
id="helloSet" class="hello.Hello">
<property p:name="Spring">property>
测试:
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Hello hello = (Hello) applicationContext.getBean("helloSet");
System.out.print(hello);
}
输出:
Hello{name='Spring', numberInt=0, numberDouble=0.0}
使用构造器注入属性值可以指定参数的位置和参数的类型,以区分重载的构造器
1. 根据索引:
<bean id="helloIndex" class="hello.Hello">
<constructor-arg name="name" value="int类型" index="0">constructor-arg>
<constructor-arg name="numberInt" value="12" index="1">constructor-arg>
bean>
输出:
Hello{name='int类型', numberInt=12, numberDouble=0.0}
2. 根据参数的不同(类型或者数量)
"helloInt" class="hello.Hello">
"name" value="int类型" type="java.lang.String">
"numberInt" value="12" type="int">
"helloDouble" class="hello.Hello">
"name" value="Double类型" type="java.lang.String">
"numberDouble" value="3.14" type="double">
测试:
Hello hello1 = (Hello) applicationContext.getBean("helloInt");
Hello hello2 = (Hello) applicationContext.getBean("helloDouble");
System.out.println(hello1);
System.out.print(hello2);
输出:
Hello{name='int类型', numberInt=12, numberDouble=0.0}
Hello{name='Double类型', numberInt=0, numberDouble=3.14}
3. 两者混用:
<bean id="hello" class="hello.Hello">
<constructor-arg name="name" value="Double类型" index="0">constructor-arg>
<constructor-arg name="numberDouble" value="3.14" type="double">constructor-arg>
bean>
输出:
Hello{name='Double类型', numberInt=0, numberDouble=3.14}
总结:
构造函数注入可以不创建无参的构造函数,
属性注入必须有无参的构造函数。
Bean属性可以type=”double”而不可以java.lang.Double