控制反转IOC(创建对象)
控制反转就是将创建对象的事情交给spring来做。
spring创建对象的方式有三种:
1、 默认的构造函数(也可参考:spring01_createObject工程)
此种方式是通过调用对象默认的构造函数来创建对象。
1. 在spring配置文件中配置要创建的对象的java类,并为此bean取一个唯一标识符(id属性的值)。
<bean id="user"class="cn.domain.User"></bean>
2. 加载spring配置文件,并获取ApplicationContext对象,通过调用此对象的getBean(“此bean的id或别名”);方法类获取cn.domain.User类的实例化对象。
ApplicationContext applicationContext = newClassPathXmlApplicationContext("applicationContext.xml");
User user = (User)applicationContext.getBean(“user”);
//这样就完成此User类的实例化了。
2、 利用静态工厂方法创建(也可参考: spring02_createObject工程)
静态工厂方法就是调用工程类的静态方法。
1. 写一个工厂类,并在此类中写一个实例化对象的静态方法。
public class ObjectFactory {
//创建User对象的示例的静态方法(可以为此静态方法注入形参,在spring配置文件中的bean标内注入参数。具体请参考spring02_createObject工程)
public static User getUserInstance(){
return new User();
}
}
//给此静态方法注入参数的测试
public static User getUserInstance(String str){
System.out.println(str);
return new User();
}
}
2. 在spring配置文件中配置此工厂类的静态方法.
<!--
bean: 标签表示注册此cn.factory.ObjectFactory工厂类
id: 为此类取一个唯一表示符(不能重复)
class: 对应的java类
factory-method: 表示静态的调用cn.factory.ObjectFactory类中的getUserInstance方法.(此属性配置的方法,表示静态方法,spring就不会创建此对象,而是直接调用此静态方法).
-->
<bean id="objectfactory"class="cn.factory.ObjectFactory" factory-method="getUserInstance"></bean>
<!—
可以用此方法给要调用的静态方法注入参数
<bean id="objectfactory"class="cn.factory.ObjectFactory"factory-method="getUserInstance">
//注入参数
<constructor-arg index="0"type="java.lang.String" value="abc"></constructor-arg>
</bean>
-->
3. 加载配置文件,并获取ApplicationContext对象,通过调用此对象的getBean(“此bean的id或别名”);方法类获取cn.domain.User类的实例化对象。
ApplicationContext applicationContext = newClassPathXmlApplicationContext("applicationContext.xml");
//当调用applicationContext对象的getBean(“objectfactory”)方法时,会去调用cn.factory.ObjectFactory工厂类的getUserInstance静态方法,并将此方法返回的User对象返回
User user = (User)applicationContext.getBean(“objectfactory”);
3、 利用实例工厂方法创建(很少用)(也可参考:spring03_createObject工程)
此方法和静态工厂方法创建的对象的区别在于,静态工厂方法不需要创建工厂对象实例,而是直接调用工厂类的静态方法。而实例工程方法需要创建工厂类的实例对象,并且调用的方法不是一个静态的方法。
1. 写一个工厂类,并在此类中写一个实例化对象的方法。
public class ObjectFactory {
//创建User对象的示例的方法
public User getUserInstance(){
return new User();
}
}
2. 在spring配置文件中配置此工厂类的方法
<!--
bean: 标签表示注册此cn.factory.ObjectFactory工厂类
id: 为此类取一个唯一表示符(不能重复)
class: 对应的java类
factory-method: 表示静态的调用cn.factory.ObjectFactory类中的getUserInstance方法。
-->
<bean id="objectfactory"class="cn.factory.ObjectFactory"></bean>
<!--
factory-bean: 表示当获取“exampleBean”时,需要实例化的bean的id。
factory-method: 表示需调用此对象的方法。
-->
<bean id="exampleBean"factory-bean="objectfactory" factory-method="getUserInstance"/>
<!-- 表示当获取“exampleBean”时,实例化id为“objectfactory”的bean对象,并调用此对象的getUserInstance方法 -->
3. 加载配置文件,并获取ApplicationContext对象,通过调用此对象的getBean(“此bean的id或别名”);方法类获取cn.domain.User类的实例化对象。
@Test
public void test1(){
//直接用spring配置文件bean标签的id来获取此User对象
User user = (User)applicationContext.getBean("exampleBean");
User user1 = (User)applicationContext.getBean("exampleBean");
//此处打印的值为true,证明以上两个User对象是一个对象
System.out.println(user==user1);
}
4、 spring是什么时候实例化bean标签中的对象的(也可参考:spring04_lazy-init)
在单例模式(第5、点中有讲)的情况下,当spring配置文件被加载时,就会马上创建所有的bean对象。
但可以在bean标签中配置一个lazy-init属性,指定此对象何时被创建如:
<!--
lazy-init: 此属性表示此对象何时被实例化。
false: 表示当加载此配置文件时,就实例化此类(缺省值)。
true: 表示当调用applicationContext.getBean("user");方法时才创建此对象
-->
<bean id="user"class="cn.domain.User" lazy-init="true"></bean>
一加载配置文件就实例化对象和调用applicationContext对象的getBean(“user”);时才创建此对象的区别:
如果在Web开发中,当加载spring配置文件时,就创建所有bean对象,就可以检查出所有的bean对象是否都写正确,这样就提高了代码的安全性,但也消耗了一部分内存。
如果调用applicationContext对象的getBean(“user”);方法时才创建此对象,那么如果有一个对象写错了,而在测试时又没有测试到,就埋下了潜在的安全隐患(所以不安全),但这样可以减少消耗内存。
5、 spring中bean的scope(域)(也可参照:spring05_bean_scope)
也就是创建此bean的模式是单例模式还是多例(普通)模式还是存储在其他域中。
spring在默认情况下创建对象的方式都是单例模式的,也可以在spring配置文件中更改bean标签scope属性的值,控制其对象的范围。
scope属性的取值:
singleton 单例默认(获取的永远都是一个对象,包括多个线程之间都是一个对象)。
prototype 多例(获取一次产生一个新的对象)
如果用此方式那么spring创建对象的时机也就变了,变成了获取的时候才创建(bean标签的lazy-init属性的值自动变成了true)
request 存储在request域中(针对Web开发)
session 存储在session域中(针对Web开发)
global session 就相当于存储在ServletContext域中(针对Web开发)
6、 bean对象的初始化和销毁(也可参考:spring06_init_destroy工程)
当一个对象在创建时和销毁时可以在配置文件中配置需要调用的方法。
如:
<bean id="user"class="cn.domain.User" init-method="init" destroy-method="destroy"scope="prototype"></bean>
当实例化此对象时spring会马上调用此对象 init-method 属性所指定的方法。
当此对象销毁时,spring会调用此对象 destroy-method 属性所指定的方法(但只有在单例模式下,spring才会调用destroy-method 属性描述的方法).
一般在spring关闭时会销毁所有的对象,用以下方法关闭spring容器:
//加载spring的配置文件(开启spring容器)
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
......
//关闭spring容器(并会销毁单例模式下生产的对象)
context.close();