前言:记录一下有关,spring生命周期相关的方法。并且探究一下源码
spring的一大好处就是可以帮我们管理对象的生命周期如:创建,初始化,销毁。这也就是ioc(控制反转)的体现,抛弃我们之前主动创建的模式,但是我们也可以自定义,初始化,和销毁方法,容器在bean执行到当前声明周期的时候就会调用我们自定义的方法,这样给了我们空间,在当前生命周期做一些额外的事情。另外这里提一下,后置处理器BeanPostProcessor
,在bean的生命周期起着非常重要的作用,可以在bean创建完成,初始化前后完成一些操作。其中声明周期方法,也跟BeanPostProcessor
密切相关,后面会记录
2019-9-18日补充图
1.bean注解直接指定 init,destory方法
先创建一个类,类中包含自定义init
和destory
方法
public class Car {
public Car(){
System.out.println("car....");
}
public void init(){
System.out.println("car...init...");
}
public void destory(){
System.out.println("car...destory...");
}
}
然后再使用@Bean
注解的时候指定
@Bean(initMethod="init",destroyMethod="destory")
public Car car(){
System.out.println("car...被放到容器当中...");
return new Car();
}
进行测试:
@Test
public void test9(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestConfig.class);
context.close();
}
控制台打印:
可以看到我们自定义的初始化 和销毁方法被执行。
现在来探究一下他的执行过程,为什么会被调用:现在给自定义的init
方法和destory
方法 打一个断点。进入debug模式
然后通过左侧的方法调用栈,看一下是如何执行到这里的。(这里我画出了三处,现在只需要关注invokeInitMethods方法,另外两处留个印象就可以)
是调用了 invokeInitMethods,看名字也很容易理解,这是调用初始化方法,接着进去看一下:重点在最后一句代码invokeCustomInitMethod(beanName, bean, mbd);
-------调用自定义的初始化方法。
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
//调用初始化方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
//invokeCustomInitMethod(beanName, bean, mbd);
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
//获得 初始 init方法的名字
String initMethodName = mbd.getInitMethodName();
//通过class 获得 init方法
final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
if (initMethod == null) {
if (mbd.isEnforceInitMethod()) {
throw new BeanDefinitionValidationException("Couldn't find an init method named '" +
initMethodName + "' on bean with name '" + beanName + "'");
}
else {
if (logger.isDebugEnabled()) {
logger.debug("No default init method named '" + initMethodName +
"' found on bean with name '" + beanName + "'");
}
// Ignore non-existent default lifecycle methods.
return;
}
}
if (logger.isDebugEnabled()) {
logger.debug("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
ReflectionUtils.makeAccessible(initMethod);
return null;
}
});
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
initMethod.invoke(bean);
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
InvocationTargetException ex = (InvocationTargetException) pae.getException();
throw ex.getTargetException();
}
}
else {
try {
ReflectionUtils.makeAccessible(initMethod);
//最后执行 intit方法。
initMethod.invoke(bean);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
这样就执行到了我们自定义的init
初始化方法,接着放行,看是如何调用,销毁方法,追寻方法栈,会发现与自定义初始化方法类似,利用反射方法调用执行:invokeCustomDestroyMethod(this.destroyMethod);
2.实现 InitializingBean与DisposableBean接口。
让Car
这个类实现这两个接口。
public class Car implements InitializingBean ,DisposableBean {
public Car(){
System.out.println("car....创建");
}
public void init(){
System.out.println("car...init...");
}
public void destory(){
System.out.println("car...destory...");
}
@Override
public void afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub
}
@Override
public void destroy() throws Exception {
// TODO Auto-generated method stub
}
}
进行测试:控制台输出
方法被成功调用。同样进入debug模式,看看,方法是如何被调用的。发现与第一种方法相同,都是调用了invokeInitMethods
方法,同样进入
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//调用bean的afterPropertiesSet方法 ********************************************
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
他调用了 bean.afterPropertiesSet,然后就执行了我们实现了InitializingBean
接口的bean的afterPropertiesSet
方法。
至于销毁方法,当容器执行了close方法之后,就发生一些调用,最后执行到我们bean的销毁方法:(如下图所示)
3.使用@PostConstruct,@PreDestory 注解
public Car(){
System.out.println("car....创建");
}
public void init(){
System.out.println("car...init...");
}
public void destory(){
System.out.println("car...destory...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Car...afterPropertiesSet....属性设置完成之后");
}
@Override
public void destroy() throws Exception {
System.out.println("Car....destroy.....销毁方法");
}
@PostConstruct
public void initmethod(){
System.out.println("Car.......initmethod...@PostConstruct");
}
@PreDestroy
public void destorymethod(){
System.out.println("Car......destorymethod...@PreDestroy...");
}
}
同样测试一下:控制台打印如下
进入debug,查看方法调用栈:发现是在pplyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
方法中被调用的,诶,这个方法就是我上面特意画出来,稍微留个心的方法。这就是bean初始化的后置处理器的before方法,
进入方法:
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//获得所有的 bean的后置处理器 然后执行每一个后置处理器的postProcessBeforeInitialization方法
//
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
看一下ioc容器当中有哪些后置处理器:发现容器当中有7个后置处理器,当遍历执行到CommonAnnotationBeanPostProcessor
时候,就进入InitDestroyAnnotationBeanPostProcessor
这个后置处理器(处理@PostConstruct,@PreDestory)
看一下InitDestroyAnnotationBeanPostProcessor里的postProcessMergedBeanDefinition()
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//获得生命周期注解
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
//调用生命周期注解方法
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}
metadata 信息如下:(内部含有生命周期注解信息)
public void invokeInitMethods(Object target, String beanName) throws Throwable {
Collection<LifecycleElement> initMethodsToIterate =
(this.checkedInitMethods != null ? this.checkedInitMethods : this.initMethods);
if (!initMethodsToIterate.isEmpty()) {
boolean debug = logger.isDebugEnabled();
for (LifecycleElement element : initMethodsToIterate) {
if (debug) {
logger.debug("Invoking init method on bean '" + beanName + "': " + element.getMethod());
}
//调用 @PostConstruct 标注的方法
element.invoke(target);
}
}
}
容器关闭销毁的时候:
@Override
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
//
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
// #postProcessBeforeDestruction方法如下:
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
// 调用生命周期的销毁方法。
metadata.invokeDestroyMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
String msg = "Invocation of destroy method failed on bean with name '" + beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex.getTargetException());
}
else {
logger.warn(msg + ": " + ex.getTargetException());
}
}
catch (Throwable ex) {
logger.error("Failed to invoke destroy method on bean with name '" + beanName + "'", ex);
}
}
对于三种 定义bean的生命方法,他们的执行顺序是怎么样的呢?【】中代表的是源码中 执行的具体操作。
*执行顺序 @PostConstruct【bean初始化之前后置处理器】》InitializingBean 【invokeInitMethods调用Setporperties】 》 直接指定init【invokeInitMethods中调用invokeCustomInitMethod】
@PreDestory 【processor.postProcessBeforeDestruction】》disposableBean 接口【((DisposableBean) bean).destroy();】》指定destory【invokeCustomDestroyMethod(methodToCall);】