1、IoC容器
ObjectFactory与ApplicationContext(继承ObjectFactory);
BeanFactory这个接口是Spring中最底层的接口,只提供最简单的IoC功能(创建Bean、获取Bean、销毁Bean)。
在一般的应用当中,一般不使用BeanFactory,推荐用ApplicationContext(应用上下文)。
1)ApplicationContext继承了BeanFactory,提供了基本的IoC功能;
2)ApplicationContext还提供了其他功能:
①支持国际化;
②支持消息机制;
③支持统一的资源加载;
④支持AOP功能;
Resource常见实现类:
1)ClassPathResource:从classpath根路径开始找配置文件;
2)FileSystemResource:从磁盘的文件路劲去找;
3)ServletContextResource:应用于web中,从web中去找配置文件。
ApplicationContext创建Bean步骤:
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloWorld helloWorld = ctx.getBean("helloWorld",HelloWorld.class); helloWorld.sayHello();
ApplicationContext常用实现类:
1)ClassPathXmlApplicationContext:读取classpath中的资源;
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
2)FileSystemXmlApplicationContext:读取指定路径的资源;
ApplicationContext ac = new FileSystemXmlApplicationContext("c:/applicationContext.xml");
3)XmlWebApplicationContext:需要在Web的环境下才能运行;
XmlWebApplicationContext ac = new XmlWebApplicationContext(); // 这时并没有初始化容器
ac.setServletContext(servletContext); // 需要指定ServletContext对象;
ac.setConfigLocation("/WEB-INF/applicationContext.xml"); // 指定配置文件路径,开头的/表示根目录
ac.refresh(); // 初始化容器
2、Bean的创建时机
1)BeanFactory需要等到获取Bean的时候才会创建Bean(延迟初始化);(桌面程序建议使用)
2)ApplicationContext在加载的时候就会创建所有的Bean;(web应用建议使用)
ApplicationContext如何延迟加载:
<bean id="helloWorld" class="com.test.HelloWorld"> // 默认不延迟初始化
<bean id="helloWorld" class="com.test.HelloWorld" lazy-init="default"> // 默认不延迟初始化
<bean id="helloWorld" class="com.test.HelloWorld" lazy-init="false"> // 不延迟初始化
<bean id="helloWorld" class="com.test.HelloWorld" lazy-init="true"> // 延迟初始化
针对当前xml中所有Bean:
<beans default-lazy-init="default | false | true">
针对指定的Bean:
<bean lazy-init="default | false | true">
3、Bean的作用域(Bean对象可以存活多久)
<bean id="" class="" scope="作用域"/>
singleton:单例,在Spring Ioc容器中仅存在一个Bean实例(默认的scope);
prototype:多例(原型),每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行new XxxBean(),不会在容器启动时创建对象;
request:用于web开发,将Bean放入request范围,request.setAttribute("xxx"),在同一个request获得同一个Bean;
session:用于web开发,将Bean放入Session范围,在同一个session中获得同一个Bean;
globalSession:一般用于Porlet应用环境,分布式系统存在全局session概念(单点登录),如果不是porlet环境,globalSession等同于Session。
在开发中主要使用scope="singleton"、scope="prototype",对于MVC中的Action使用prototype类型(否则会有安全性问题),其他使用singleton。
4、Bean的初始化和销毁方法
<!--
Class clz = Class.forName("com.test.HelloWorld");
①SomeBean bean = (SomBean) clz.newInstance();
②Method initMethod = clz.getMethod("init");
initMethod.invoke(bean);
...bean的其他操作
③Method destroyMethod = clz.getMethod("destroy");
destroyMethod.invoke(bean);
-->
<bean id="helloWorld" class="com.test.HelloWorld" init-method="init" destroy-method="destroy">
如DataSource、SessionFactory等最终都需要关闭资源,在Bean销毁之前,都要调用close方法。
<bean id="..." class="..." init-method="该类中的初始化方法名" destroy-method="该类中的销毁方法名"/>
init-method:Bean生命周期初始化方法,对象创建后就进行调用;
destroy-method:容器被销毁的时候,如果Bean被容器管理,会调用该方法。
如果Bean的scope="prototype",那么容器只负责创建和初始化,它并不会被spring容器管理。
如果不使用Spring容器进行测试,而使用传统测试,Spring容器将非正常关闭。
单元测试的线程很短(获取网络信息时,不要使用单元测试,而要使用主方法)。
若要正常关闭Spring容器,使用AbstractApplicationContext
// 关闭上下文对象
ctx.close();
// 最好的方式是:把Spring线程昨晚JVM的子线程
ctx.registerShutdownHook();
5、Bean的生命周期