spring源码:初始化方法

目的

spring提供了三种初始化方法:
1、@PostConstruct、@PreDestory
2、实现 InitializingBean DisposableBean 接口,并实现对应的afterPropertiesSet()和destroy()方法
3、设置init-method和destory-method
本文主要解析三个初始化和销毁方法的源码

源码

1、三种初始化方法的优先级从高到低;在spring官方文档也有明确指出

Multiple lifecycle mechanisms configured for the same bean, with
different initialization methods, are called as follows:
  Methods annotated with @PostConstruct
  afterPropertiesSet() as defined by the InitializingBean callback interface
 A custom configured init() method
Destroy methods are called in the same order:
  Methods annotated with @PreDestroy
  destroy() as defined by the DisposableBean callback interface
  A custom configured destroy() method

优先级之所以是这样,和源码中对三种配置方式处理的优先级有关系

测试代码

public class UserService04 implements InitializingBean,DisposableBean {

    public UserService04() {
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("实现接口DisposableBean销毁");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("实现接口InitializingBean初始化");
    }

    public void init(){
        System.out.println("initMethod");
    }

    public void destroyConfig(){
        System.out.println("destroyMethod");
    }

    @PostConstruct
    public void testPost(){
        System.out.println("注解PostConstruct init");
    }

    @PreDestroy
    public void testDestroy(){
        System.out.println("注解PreDestroy 销毁");
    }
}


@Configuration
@ComponentScan("com.springsource.initmethod")
public class InitMethodConfig {
    @Bean(initMethod = "init",destroyMethod = "destroyConfig")
    public UserService04 testUserService04(){
        return new UserService04();
    }
}

2、初始化方法
初始化方法的代码位置是在

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

在该方法中,完成了bean的初始化方法回调和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);
}

对于@PostConstruct和@PreDestroy这两个注解,是在applyBeanPostProcessorsBeforeInitialization()中完成处理的,而剩下两种初始化方法,是在invokeInitMethods()中完成的,所以,对于注解的方式,优先级最高

我们先来说invokeInitMethods()方法,也就是后两种初始化方法:

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {
	//这里是处理实现了InitializingBean接口的初始化方法
	boolean isInitializingBean = (bean instanceof InitializingBean);
	if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
		if (logger.isTraceEnabled()) {
			logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
		}
		if (System.getSecurityManager() != null) {
			try {
				AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
					((InitializingBean) bean).afterPropertiesSet();
					return null;
				}, getAccessControlContext());
			}
			catch (PrivilegedActionException pae) {
				throw pae.getException();
			}
		}
		else {
			// 调用实现类中的afterPropertiesSet()方法
			((InitializingBean) bean).afterPropertiesSet();
		}
	}
	//这里是来处理init-method方法
	if (mbd != null && bean.getClass() != NullBean.class) {
		String initMethodName = mbd.getInitMethodName();
		if (StringUtils.hasLength(initMethodName) &&
				!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
				!mbd.isExternallyManagedInitMethod(initMethodName)) {
			invokeCustomInitMethod(beanName, bean, mbd);
		}
	}
}

可以看到,代码中是先判断当前bean是否是InitializingBean的实现类,然后优先调用了afterProperties();
然后再调用beanDefinition中对应的initMethod;需要说明的是:initMethod这种方式,对应的初始化方法和销毁方法,是在将bean添加到beanDefinitionMap中的时候,对bean进行了解析,获取到对应的initMethod和destroyMethod,然后放到了beanDefinition中

我们接着来说@PostConstruct和@PreDestroy注解的处理
该注解是由CommonAnnotationBeanPostProcessor的postProcessBeforeInitialization和postProcessBeforeDestruction来处理的

@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
	/**
	 * 在初始化bean的时候,会在这里处理注解的初始化方法 @PostConstruct
	 * 从cache中获取到当前bean的元对象
	 * 在invokeInitMethods方法中,就是
	 */
	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;
}

这是初始化方法对应的处理类,在此之前,在第三个后置处理器调用的时候,会调用到org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition;在该方法中,会找出当前bean中对应的@PostConstruct和@PreDestroy注解对应的方法,存入到lifecycleMetadataCache这个map中

然后在调用postProcessBeforeInitialization()方法的时候,注解从map中遍历所有的初始化方法,然后依次调用

3、销毁方法
三个销毁方法是在调用

@Override
public void destroy() {
	if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
		for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
			//这里是处理@PreDestroy注解对应的方法
			processor.postProcessBeforeDestruction(this.bean, this.beanName);
		}
	}

	if (this.invokeDisposableBean) {
		if (logger.isDebugEnabled()) {
			logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
		}
		try {
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
					((DisposableBean) this.bean).destroy();
					return null;
				}, this.acc);
			}
			else {
				// 处理实现了DisposableBean接口的类
				((DisposableBean) this.bean).destroy();
			}
		}
		catch (Throwable ex) {
			String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
			if (logger.isDebugEnabled()) {
				logger.warn(msg, ex);
			}
			else {
				logger.warn(msg + ": " + ex);
			}
		}
	}

	if (this.destroyMethod != null) {
		//处理destroyMethod方法
		invokeCustomDestroyMethod(this.destroyMethod);
	}
	else if (this.destroyMethodName != null) {
		Method methodToCall = determineDestroyMethod(this.destroyMethodName);
		if (methodToCall != null) {
			invokeCustomDestroyMethod(methodToCall);
		}
	}
}

spring源码:初始化方法_第1张图片
调用链是这样的,可以看到,在销毁bean的时候,也是按照文章开头的顺序来进行销毁的;而对应的原理和初始化方法调用的原理是一样的

你可能感兴趣的:(spring源码,spring)