本人博客已搬家,新地址为:http://yidao620c.github.io/
spring在DefaultSingletonBeanRegistry类提供了一个用于缓存单例Bean的缓存器,它是一个用HashMap实现的缓存器,单实例的Bean以beanName为键保存在这个HashMap中。在初始化BeanFactory的时候,必须为其指定一个日志框架,一般来讲使用Log4j或者lsf4J即可。
如果说BeanFactory是spring的心脏,那么ApplicationContext就是完整的身躯了。ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能。在BeanFactory中,很多功能需要编程实现,但是ApplicationContext可以配置实现。
ApplicationContext的主要派生类是ClassPathXmlApplicationContext和FileSystemXmlApplicationContext,前者默认从类路径加载配置文件,后者默认从文件系统装载配置文件。
ApplicationContext跟BeanFactory的很大一个区别是:ApplicationContext在初始化的时候就实例化了所有单例Bean,而BeanFactory的策略是lazy load。
Bean的生命周期详解:
1,通过getBean()调用某一个Bean
2,* 如果容器注册了InstantiationAwareBeanPostProcessor接口,调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()方法
3,根据配置调用Bean构造函数或者是工厂方法实例化Bean
4,* 如果容器注册了InstantiationAwareBeanPostProcessor接口,调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation()方法
5,* 如果容器注册了InstantiationAwareBeanPostProcessor接口,在设置每个属性之前会先调用InstantiationAwareBeanPostProcessor的postProcessPropertyValues()方法,这个和下面的6在一个属性设置循环体中
6,根据配置文件设置属性值
7,如果Bean实现了BeanNameAware接口,调用BeanNameAware的setBeanName()方法,将配置文件中该Bean对应的名称设置到Bean中
8,如果Bean实现了BeanFactoryAware接口,调用BeanFactoryAware的setBeanFactory()方法,将BeanFactory容器实例设置到Bean中
9,* 如果BeanFactory装配了BeanPostProcessor后处理器,调用BeanPostProcessor的postProcessBeforeInitialization()方法,对Bean进行加工处理。用户可以使用该方法对某些Bean进行特殊处理,甚至改变Bean的行为,BeanPostProcessor在spring里面占用特殊地位,spring容器所提供的AOP,动态代理等都是通过BeanPostProcessor实施的
10,如果Bean实现了InitializationBean的接口,调用InitializationBean的afterPropertiesSet()方法
11,如果Bean定义了init-method,通过init-method属性配置调用相应的初始化方法
12,* 如果BeanFactory装配了BeanPostProcessor后处理器,容器再次获得对Bean进行加工处理的机会,调用BeanPostProcessor的postProcessAfterInitialization()方法
13-1,如果是singleton的bean就放入spring缓冲池,然后容器销毁的时候,如果Bean实现了DisposableBean接口,此时会调用DisposableBean的afterPropertiesSet()方法,然后再调用destory-method方法,Bean周期结束。
13-2,如果是prototype的话就将准备就绪的Bean交给调用者
注:
Bean级生命周期接口方法:BeanNameAware、BeanFactoryAware、InitializationBean、DisposableBean,这些接口方法友Bean类直接实现
容器级生命周期接口方法:在上面带*号的都是,由InstantiationAwareBeanPostProcessor和BeanPostProcessor这两个接口实现,一般称它们为后处理器。它们独立于Bean,实现类以容器附加装置的形式注册到spring容器中并通过接口反射为spring容器预先识别。当spring容器创建任何Bean的时候,这些后处理器都会发生作用,所以是全局性的。
从spring3.0开始支持基于类注解的配置方式:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.springzoo.Car; @Configuration public class Beans { @Bean(name = "car") public Car buildCar() { Car car = new Car(); car.setBrand("红旗CA72"); car.setMaxSpeed(200); return car; } }
spring为基于注解类的配置提供了专门的ApplicationContext实现类:AnnotationConfigApplicationContext,来看看怎么使用的:
ApplicationContext ctx = new AnnotationConfigApplicationContext(Beans.class); Car car =ctx.getBean("car",Car.class);
WebApplicationContext是专门为Web应用准备的,它允许从相对于Web根目录装载配置文件来完成初始化工作,有个工具类WebApplicationContextUtils,通过它的getWebApplicationContext(ServletContext sc)方法,可以从ServletContext中获取WebApplicationContext实例。spring2.0还在WebApplicationContext中为Bean增加了三个新的作用域:request、session、global session,在非web环境下,只有singleton和prototyoe两种作用域。
WebApplicationContext中有一个常量:ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,以此为键存在ServletContext中,如此实现了WebApplicationContext和ServletContext的互访:
ServletContext sc = WebApplicationContext.getServletContext()
WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(sc)
ConfigurableWebApplicationContext扩展了WebApplicationContext,它允许通过配置文件实例化WebApplicationContext,它有两个重要方法:
* setServletContext(ServletContext sc):为spring设置Web应用上下文
* setConfigLocations(String[] configLocations):设置spring配置文件路径,一般都是现对于Web根目录,如:/WEB-INF/springzoo-dao.xml、/WEB-INF/springzoo-service.xml
初始化:
通过在web.xml中定义ContextLoaderServlet或者是ContextLoaderListener即可:
<!-- ① 从类路径下加载spring配置文件,classpath关键字特指类路径下加载 多个配置文件用逗号,分开--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml,/WEB-INF/springzoo-service.xml</param-value> </context-param> <!-- ② 负责启动spring容器的监听器,该监听器在web容器启动时候自动运行, 它将引用①处的上下文参数获得的spring配置文件地址--> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>