Spring实际上是一个容器框架,可以配置各种bean(action/service/domain/dao...),并且可以维护bean与bean的关系。
ioc是什么?
答 :ioc(inverse of controll ) 控制反转: 所谓控制反转就是把创建对象(bean),和维护对象(bean)的关系的权利从程序中转移到spring的容器(applicationContext.xml),而程序本身不再维护。
DI是什么?
答: di(dependency injection) 依赖注入: 实际上di和ioc是同一个概念,spring设计者认为di更准确表示spring核心技术。
下面以BeanFactory为例,说明一个Bean的生命周期活动:
1.Bean的建立
由BeanFactory读取Bean定义文件,并生成各个实例。
2.Setter注入
执行Bean的属性依赖注入。
3.BeanNameAware的setBeanName()
如果Bean类实现了org.springframework.beans.factory.BeanNameAware接口,则执行其setBeanName()方法。
4.BeanFactoryAware的setBeanFactory()
如果Bean类实现了org.springframework.beans.factory.BeanFactoryAware接口,则执行其setBeanFactory()方法。
5.BeanPostProcessors的processBeforeInitialization()
容器中如果有实现org.springframework.beans.factory.BeanPostProcessors接口的实例,则任何Bean在初始化之前都会执行这个实例的processBeforeInitialization()方法。
6.InitializingBean的afterPropertiesSet()
如果Bean类实现了org.springframework.beans.factory.InitializingBean接口,则执行其afterPropertiesSet()方法。
7.Bean定义文件中定义init-method
在Bean定义文件中使用“init-method”属性设定方法名称,如下:
.......
这时会执行initMethod()方法,注意,这个方法是不带参数的。
8.BeanPostProcessors的processAfterInitialization()
容器中如果有实现org.springframework.beans.factory.BeanPostProcessors接口的实例,则任何Bean在初始化之前都会执行这个实例的processAfterInitialization()方法。
9.DisposableBean的destroy()
在容器关闭时,如果Bean类实现了org.springframework.beans.factory.DisposableBean接口,则执行它的destroy()方法。
10.Bean定义文件中定义destroy-method
在容器关闭时,可以在Bean定义文件中使用“destory-method”定义的方法
.......
这时会执行destroyMethod()方法,注意,这个方法是不带参数的。
以上就是BeanFactory维护的一个Bean的生命周期。下面这个图可能更直观一些:
如果使用ApplicationContext来维护一个Bean的生命周期,则基本上与上边的流程相同,只不过在执行BeanNameAware的setBeanName()后,若有Bean类实现了org.springframework.context.ApplicationContextAware接口,则执行其setApplicationContext()方法,然后再进行BeanPostProcessors的processBeforeInitialization()
实际上,ApplicationContext除了向BeanFactory那样维护容器外,还提供了更加丰富的框架功能,如Bean的消息,事件处理机制等。
小结: 我们实际开发中往往,没有用的这么的过程,常见的是:
实例化
调用set方法设置属性
如果bean 和 一个前置处理器关联
使用我们的bean
如果bean 和 一个后置处理器关联
容器关闭
在这里在补充讲一下BeanFactory(Spring心脏) 与ApplicationContext(身躯)比较:
BeanFactory在初始化容器的时候,并未实例化Bean,直到第一次访问Bean时才实例化目标Bean;
ApplicationContext在初始化应用上下文时就实例化所有单实例的Bean(所以初始化比较耗时,不过稍后使用不存在“第一次惩罚”)
另外,Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:
1、Bean自身的方法 :
这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法
2、Bean级生命周期接口方法 :
这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法
3、容器级生命周期接口方法 :
这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
4、工厂后处理器接口方法 :
这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器 接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。
最后来个演示:
首先是一个bean User
package com.sunsharing.beanlife;import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.BeanFactoryAware;import org.springframework.beans.factory.BeanNameAware;import org.springframework.beans.factory.InitializingBean;import org.springframework.beans.factory.DisposableBean;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;/** * Created by nyp on 2015/2/27. */public class User implements BeanNameAware,BeanFactoryAware,ApplicationContextAware,InitializingBean,DisposableBean{ private String name; private Integer age; public Integer getAge() { return age; } public void setAge(Integer age) { System.out.println("属性age set方法:setName(Integer age) 被调用"); this.age = age; } public String getName() { return name; } public void setName(String name) { System.out.println("属性name set方法:setName(String name) 被调用"); this.name = name; } public User(){ System.out.println("构造函数:User "); } public void sayHi(){ System.out.println("hi "+ name); } //该方法可以给arg0表示正在被实例化得bean id public void setBeanName(String arg0) { // TODO Auto-generated method stub System.out.println("BeanNameAware接口:setBeanName 被调用 值"+arg0); } //该方法可以传递beanFactroy public void setBeanFactory(BeanFactory arg0) throws BeansException { // TODO Auto-generated method stub System.out.println("BeanFactoryAware接口:setBeanFactory 被调用"+arg0); } //该方法传递ApplicationContext public void setApplicationContext(ApplicationContext arg0) throws BeansException { // TODO Auto-generated method stub System.out.println("ApplicationContextAware接口:setApplicationContext "+arg0); } //这是InitializingBean接口方法 public void afterPropertiesSet() throws Exception { // TODO Auto-generated method stub System.out.println("InitializingBean接口:InitializingBean.afterPropertiesSet()"); } // 这是DiposibleBean接口方法 public void destroy() throws Exception { System.out.println("DiposibleBean接口:调用DiposibleBean.destory()"); } //定制我们的初始化方法 public void myinit(){ System.out.println("自定义myinit方法 被调用"); } //定制我们的销毁方法 public void mydestory(){ System.out.println("自定义mydestory 释放各种资源"); }}
然后是MyBeanPostProcessor
package com.sunsharing.beanlife;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;/** * Created by nyp on 2015/2/27. */public class MyBeanPostProcessor implements BeanPostProcessor { public Object postProcessAfterInitialization(Object arg0, String arg1) throws BeansException { // TODO Auto-generated method stub System.out.println("BeanPostProcessor接口:postProcessAfterInitialization 函数被调用 "+arg0+"被创建的时间是"+new java.util.Date()); return arg0; } public Object postProcessBeforeInitialization(Object arg0, String arg1) throws BeansException { // TODO Auto-generated method stub System.out.println("BeanPostProcessor接口:postProcessBeforeInitialization 函数被调用"); return arg0; }}
接着ApplicatationContext.xml的配置
小明 2015
最后用一个App类 测试下,
package com.sunsharing.beanlife;/** * Created by nyp on 2015/2/27. */import org.springframework.beans.factory.BeanFactory;import org.springframework.context.support.ClassPathXmlApplicationContext;public class App { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub System.out.println("==========开始初始化容器!=========="); BeanFactory factory=new ClassPathXmlApplicationContext("applicationContext.xml"); System.out.println("==========初始化成功!=========="); User u=(User) factory.getBean("personService"); u.sayHi(); System.out.println("==========开始关闭容器!=========="); ((ClassPathXmlApplicationContext)factory).registerShutdownHook(); }}
然后华丽丽的结果出来了,如下:
==========开始初始化容器!==========[INFO ] [22:22:15] org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7b7381ef: startup date [Fri Feb 27 22:22:15 CST 2015]; root of context hierarchy[INFO ] [22:22:15] org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [applicationContext.xml][INFO ] [22:22:17] org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@229a8e52: defining beans [personService,myBeanPostProcessor]; root of factory hierarchy构造函数:User 属性name set方法:setName(String name) 被调用属性age set方法:setName(Integer age) 被调用BeanNameAware接口:setBeanName 被调用 值personServiceBeanFactoryAware接口:setBeanFactory 被调用org.springframework.beans.factory.support.DefaultListableBeanFactory@229a8e52: defining beans [personService,myBeanPostProcessor]; root of factory hierarchyApplicationContextAware接口:setApplicationContext org.springframework.context.support.ClassPathXmlApplicationContext@7b7381ef: startup date [Fri Feb 27 22:22:15 CST 2015]; root of context hierarchyBeanPostProcessor接口:postProcessBeforeInitialization 函数被调用InitializingBean接口:InitializingBean.afterPropertiesSet()自定义myinit方法 被调用BeanPostProcessor接口:postProcessAfterInitialization 函数被调用 com.sunsharing.beanlife.User@fc85b94被创建的时间是Fri Feb 27 22:22:17 CST 2015==========初始化成功!==========hi 小明==========开始关闭容器!==========[INFO ] [22:22:17] org.springframework.context.support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@7b7381ef: startup date [Fri Feb 27 22:22:15 CST 2015]; root of context hierarchy[INFO ] [22:22:17] org.springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@229a8e52: defining beans [personService,myBeanPostProcessor]; root of factory hierarchyDiposibleBean接口:调用DiposibleBean.destory()自定义mydestory 释放各种资源Process finished with exit code 0
这样打印的结果清晰明了,相信对理解spring bean生命周期的理解会更加深刻。