聊聊InitDestroyAnnotationBeanPostProcessor

本文主要研究一下InitDestroyAnnotationBeanPostProcessor

DestructionAwareBeanPostProcessor

spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java

public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {

	/**
	 * Apply this BeanPostProcessor to the given bean instance before its
	 * destruction, e.g. invoking custom destruction callbacks.
	 * 

Like DisposableBean's {@code destroy} and a custom destroy method, this * callback will only apply to beans which the container fully manages the * lifecycle for. This is usually the case for singletons and scoped beans. * @param bean the bean instance to be destroyed * @param beanName the name of the bean * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.DisposableBean#destroy() * @see org.springframework.beans.factory.support.AbstractBeanDefinition#setDestroyMethodName(String) */ void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException; /** * Determine whether the given bean instance requires destruction by this * post-processor. *

The default implementation returns {@code true}. If a pre-5 implementation * of {@code DestructionAwareBeanPostProcessor} does not provide a concrete * implementation of this method, Spring silently assumes {@code true} as well. * @param bean the bean instance to check * @return {@code true} if {@link #postProcessBeforeDestruction} is supposed to * be called for this bean instance eventually, or {@code false} if not needed * @since 4.3 */ default boolean requiresDestruction(Object bean) { return true; } }

DestructionAwareBeanPostProcessor继承了BeanPostProcessor方法,它定义了postProcessBeforeDestruction、requiresDestruction两个方法

InitDestroyAnnotationBeanPostProcessor

spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java

public class InitDestroyAnnotationBeanPostProcessor
		implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, Serializable {

	@Nullable
	private Class initAnnotationType;

	@Nullable
	private Class destroyAnnotationType;

	private int order = Ordered.LOWEST_PRECEDENCE;	

	@Override
	public int getOrder() {
		return this.order;
	}


	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) {
		LifecycleMetadata metadata = findLifecycleMetadata(beanType);
		metadata.checkConfigMembers(beanDefinition);
	}

	@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;
	}

	@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 = "Destroy method on bean with name '" + beanName + "' threw an exception";
			if (logger.isDebugEnabled()) {
				logger.warn(msg, ex.getTargetException());
			}
			else {
				logger.warn(msg + ": " + ex.getTargetException());
			}
		}
		catch (Throwable ex) {
			logger.warn("Failed to invoke destroy method on bean with name '" + beanName + "'", ex);
		}
	}

	@Override
	public boolean requiresDestruction(Object bean) {
		return findLifecycleMetadata(bean.getClass()).hasDestroyMethods();
	}


	private LifecycleMetadata findLifecycleMetadata(Class clazz) {
		if (this.lifecycleMetadataCache == null) {
			// Happens after deserialization, during destruction...
			return buildLifecycleMetadata(clazz);
		}
		// Quick check on the concurrent map first, with minimal locking.
		LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
		if (metadata == null) {
			synchronized (this.lifecycleMetadataCache) {
				metadata = this.lifecycleMetadataCache.get(clazz);
				if (metadata == null) {
					metadata = buildLifecycleMetadata(clazz);
					this.lifecycleMetadataCache.put(clazz, metadata);
				}
				return metadata;
			}
		}
		return metadata;
	}	
}		

InitDestroyAnnotationBeanPostProcessor实现了BeanPostProcessor接口定义的postProcessBeforeInitialization方法,DestructionAwareBeanPostProcessor接口的postProcessBeforeInitialization、requiresDestruction方法;其中postProcessBeforeInitialization方法先通过findLifecycleMetadata找到LifecycleMetadata,然后执行invokeInitMethods方法;postProcessBeforeDestruction方法也是先通过findLifecycleMetadata找到LifecycleMetadata,然后执行invokeDestroyMethods方法

LifecycleMetadata

	private class LifecycleMetadata {

		private final Class targetClass;

		private final Collection initMethods;

		private final Collection destroyMethods;

		@Nullable
		private volatile Set checkedInitMethods;

		@Nullable
		private volatile Set checkedDestroyMethods;

		public LifecycleMetadata(Class targetClass, Collection initMethods,
				Collection destroyMethods) {

			this.targetClass = targetClass;
			this.initMethods = initMethods;
			this.destroyMethods = destroyMethods;
		}

		public void checkConfigMembers(RootBeanDefinition beanDefinition) {
			Set checkedInitMethods = new LinkedHashSet<>(this.initMethods.size());
			for (LifecycleElement element : this.initMethods) {
				String methodIdentifier = element.getIdentifier();
				if (!beanDefinition.isExternallyManagedInitMethod(methodIdentifier)) {
					beanDefinition.registerExternallyManagedInitMethod(methodIdentifier);
					checkedInitMethods.add(element);
					if (logger.isTraceEnabled()) {
						logger.trace("Registered init method on class [" + this.targetClass.getName() + "]: " + element);
					}
				}
			}
			Set checkedDestroyMethods = new LinkedHashSet<>(this.destroyMethods.size());
			for (LifecycleElement element : this.destroyMethods) {
				String methodIdentifier = element.getIdentifier();
				if (!beanDefinition.isExternallyManagedDestroyMethod(methodIdentifier)) {
					beanDefinition.registerExternallyManagedDestroyMethod(methodIdentifier);
					checkedDestroyMethods.add(element);
					if (logger.isTraceEnabled()) {
						logger.trace("Registered destroy method on class [" + this.targetClass.getName() + "]: " + element);
					}
				}
			}
			this.checkedInitMethods = checkedInitMethods;
			this.checkedDestroyMethods = checkedDestroyMethods;
		}

		public void invokeInitMethods(Object target, String beanName) throws Throwable {
			Collection checkedInitMethods = this.checkedInitMethods;
			Collection initMethodsToIterate =
					(checkedInitMethods != null ? checkedInitMethods : this.initMethods);
			if (!initMethodsToIterate.isEmpty()) {
				for (LifecycleElement element : initMethodsToIterate) {
					if (logger.isTraceEnabled()) {
						logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod());
					}
					element.invoke(target);
				}
			}
		}

		public void invokeDestroyMethods(Object target, String beanName) throws Throwable {
			Collection checkedDestroyMethods = this.checkedDestroyMethods;
			Collection destroyMethodsToUse =
					(checkedDestroyMethods != null ? checkedDestroyMethods : this.destroyMethods);
			if (!destroyMethodsToUse.isEmpty()) {
				for (LifecycleElement element : destroyMethodsToUse) {
					if (logger.isTraceEnabled()) {
						logger.trace("Invoking destroy method on bean '" + beanName + "': " + element.getMethod());
					}
					element.invoke(target);
				}
			}
		}

		public boolean hasDestroyMethods() {
			Collection checkedDestroyMethods = this.checkedDestroyMethods;
			Collection destroyMethodsToUse =
					(checkedDestroyMethods != null ? checkedDestroyMethods : this.destroyMethods);
			return !destroyMethodsToUse.isEmpty();
		}
	}

LifecycleMetadata的invokeInitMethods遍历checkedInitMethods通过反射执行init方法,invokeDestroyMethods则是遍历checkedDestroyMethods通过反射执行destroy方法

CommonAnnotationBeanPostProcessor

spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java

public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor
		implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {

	public CommonAnnotationBeanPostProcessor() {
		setOrder(Ordered.LOWEST_PRECEDENCE - 3);
		setInitAnnotationType(PostConstruct.class);
		setDestroyAnnotationType(PreDestroy.class);
		ignoreResourceType("javax.xml.ws.WebServiceContext");
	}

	//......
}		

CommonAnnotationBeanPostProcessor继承了InitDestroyAnnotationBeanPostProcessor,其构造器设置了initAnnotationType为PostConstruct.class,设置destroyAnnotationType为PreDestroy.class

小结

InitDestroyAnnotationBeanPostProcessor实现了BeanPostProcessor接口定义的postProcessBeforeInitialization方法,DestructionAwareBeanPostProcessor接口的postProcessBeforeInitialization、requiresDestruction方法;其中postProcessBeforeInitialization方法先通过findLifecycleMetadata找到LifecycleMetadata,然后执行invokeInitMethods方法;postProcessBeforeDestruction方法也是先通过findLifecycleMetadata找到LifecycleMetadata,然后执行invokeDestroyMethods方法。

你可能感兴趣的:(java,开发语言,spring)