Web容器Tomcat或Resin启动的时候会去加载web.xml。我们在web.xml中增加
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
或:
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
那么Web容器会默认自动加载/WEB-INF/applicationContext.xml初始化,一般通过
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
去寻找类路径(一般我们设置为WebRoot/WEB-INF/classes)下面的applicationContext.xml。
(1)Bean的建立:容器寻找Bean的定义信息并将其实例化。
(2)属性注入:使用依赖注入,Spring按照Bean定义信息配置Bean所有属性
(3)BeanNameAware的setBeanName():如果Bean类有实现org.springframework.beans.BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。
(4)BeanFactoryAware的setBeanFactory():如果Bean类有实现org.springframework.beans.factory.BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。
(5)BeanPostProcessors的ProcessBeforeInitialization():如果有org.springframework.beans.factory.config.BeanPostProcessors和Bean关联,那么其postProcessBeforeInitialization()方法将被将被调用。
(6)initializingBean的afterPropertiesSet():如果Bean类已实现org.springframework.beans.factory.InitializingBean接口,则执行他的afterProPertiesSet()方法。
(7)Bean定义文件中定义init-method:可以在Bean定义文件中使用"init-method"属性设定方法名称例如。如果有以上设置的话,则执行到这个阶段,就会执行initBean()方法。
(8)BeanPostProcessors的ProcessaAfterInitialization():如果有任何的BeanPostProcessors实例与Bean实例关联,则执行BeanPostProcessors实例的ProcessaAfterInitialization()方法。
此时,Bean已经可以被应用系统使用,并且将保留在BeanFactory中知道它不在被使用。有两种方法可以将其从BeanFactory中删除掉
(1)DisposableBean的destroy():在容器关闭时,如果Bean类有实现org.springframework.beans.factory.DisposableBean接口,则执行他的destroy()方法。
(2)Bean定义文件中定义destroy-method:在容器关闭时,可以在Bean定义文件中使用"destroy-method"属性设定方法名称。
如果有以上设定的话,则进行至这个阶段时,就会执行destroy()方法,如果是使用ApplicationContext来生成并管理Bean的话则稍有不同,使用ApplicationContext来生成及管理Bean实例的话,在执行BeanFactoryAware的setBeanFactory()阶段后,若Bean类上有实现org.springframework.context.ApplicationContextAware接口,则执行其setApplicationContext()方法,接着才执行BeanPostProcessors的ProcessBeforeInitialization()及之后的流程。
代码测试:
在applicationContext.xml中配置如下:
<bean id="teacher" class="com.lxq.test.Teacher" init-method="init" destroy-method="destroy"> <constructor-arg type="java.lang.String" index="0"> <value>default_xml_constructor</value> </constructor-arg> <property name="name"> <value>default_xml_property</value> </property> </bean> <bean id="myBeanPostProcessor" class="com.lxq.test.MyBeanPostProcessor" > </bean>
Teacher类,继承一些接口:
package com.lxq.test; 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; public class Teacher implements BeanFactoryAware, BeanNameAware, InitializingBean { private String name; private Integer age; private String beanName; private BeanFactory beanFactory; public void setName(String name) { System.out.println("这是在调用Teacher-setName,将名字由" + this.name + "设置为" + name); this.name = name; } public Teacher(String name) { System.out.println("这是在调用Teacher的构造方法,将名字由" + this.name + "设置为" + name); } public void init() { this.name = "default_init"; System.out.println("这是Teacher-init,将名字由" + this.name + "设置为default_init"); } public void destroy() { System.out.println("这是Teacher-destroy"); } public void display() { System.out.println(this.name + "-" + this.age); } public void afterPropertiesSet() throws Exception { System.out.println("InitializingBean-afterPropertiesSet:name is " + name); } public void setBeanName(String name) { this.beanName=name; System.out.println("BeanNameAware-setBeanName,beanName is " + name); } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory=beanFactory; System.out.println("BeanFactoryAware-setBeanFactory,beanFactory is " + beanFactory); } }
package com.lxq.test; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; /** * * @author lxq * 一旦MyBeanPostProcessor实现了接口BeanPostProcessor,并在xml中或利用annotation进行bean的注册,那么所有的bean都会执行下面的两个方法 */ public class MyBeanPostProcessor implements BeanPostProcessor { public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof Teacher) { System.out .println("BeanPostProcessor-postProcessAfterInitialization"); } return bean; } public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof Teacher) { ((Teacher) bean).setName("default_processor"); System.out .println("BeanPostProcessor-postProcessBeforeInitialization,这是在init之前进行修改bean的属性值,把name修改为default_processor"); } return bean; } }
package com.lxq.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class BeanLifecycleManangeTest { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext( new String[] { "beans.xml" }); /** 调用getbean方法 */ Teacher t = (Teacher) ac.getBean("teacher"); t.display(); /** 调用close方法关闭bean */ AbstractApplicationContext aac = (AbstractApplicationContext) ac; aac.close(); } }
这是在调用Teacher的构造方法,将名字由null设置为default_xml_constructor 这是在调用Teacher-setName,将名字由null设置为default_xml_property BeanNameAware-setBeanName,beanName is teacher BeanFactoryAware-setBeanFactory,beanFactory is org.springframework.beans.factory.support.DefaultListableBeanFactory@39cf4a2c: defining beans [generatedOrderidServiceBean,其他的省略]; root of factory hierarchy 这是在调用Teacher-setName,将名字由default_xml_property设置为default_processor BeanPostProcessor-postProcessBeforeInitialization,这是在init之前进行修改bean的属性值,把name修改为default_processor InitializingBean-afterPropertiesSet:name is default_processor 这是Teacher-init,将名字由default_init设置为default_init BeanPostProcessor-postProcessAfterInitialization default_init-null 这是Teacher-destroy
查看AbstractAutowireCapableBeanFactory的initializeBean,可以看到一个大概的执行过程,查看每个方法中更具体的可以发现基本就是上面所讲的bean的生命周期或者说只是创建过程。
invokeAwareMethods
applyBeanPostProcessorsBeforeInitialization
invokeInitMethods
applyBeanPostProcessorsAfterInitialization
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { invokeAwareMethods(beanName, bean); return null; } }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }