BeanPostProcessor, Initializing Bean, init-method Analysis of Spring

Posted by mm00 on Tue, 08 Oct 2019 08:15:13 +0200

TIPS:Spring has actually provided us with some hook methods to do some post-processing business after initializing beans. The so-called post-processing is the Bean Post Processor in this article.
BeanPost Processor provides two callback methods in which you can implement some customized business logic.

1.BeanPostProcessor Source Parsing

public interface BeanPostProcessor {

	/**
	 * This method is called back before the InitializingBean method afterPropertiesSet and the init-method method method is defined. The return value may be a wrapper class of the original object.
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
	 * This method is called back after the InitializingBean method afterProperties Set and the init-method method method is defined. The return value may be a wrapper class of the original object.
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

The above two methods are called after the Bean initialization is completed. They are hook methods provided by Spring. Looking at method names, they seem to be called before and after the Bean initialization, but in fact they are not. They are hook methods provided by Spring.
Where are the two hook methods invoked when the Bean initialization is complete? Look at the following example.

2. Look at the initializeBean method in the AbstractAutowireCapableBeanFactory class, which of course calls the postprocessor.

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
		    //If Bean implements BeanNameAware, BeanClassLoader Aware, BeanFactoryAware, then initialize the attribute value of Bean
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
		    //The applyBeanPostProcessors BeforeInitialization method is a method in the AutowireCapableBeanFactory interface.
		    //The postProcessBeforeInitialization method used to call the postprocessor BeanPostProcessor
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
		    //If a Bean inherits the InitializingBean class, it will call the afterPropertiesSet method, if the init-method method method is set.
		    //The init-method method method is called, and the afterPropertiesSet method is called before the init-method method method.
			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()) {
		//The applyBeanPostProcessors AfterInitialization method is a method in the AutowireCapableBeanFactory interface.
		//The postProcessAfterInitialization method used to call the postprocessor BeanPostProcessor
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

ApplyBean PostProcessors BeforeInitialization Post Processing Method for Calling Beans

	@Override
	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

postProcessAfterInitialization Post Processing Method for Calling Bean s

	@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

Initialize Bean's Aware property value

	private void invokeAwareMethods(final String beanName, final Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

Up to here, the invocation logic of post processor BeanPostProcessor, Initializing Bean, init-method has been analyzed. If you don't understand or have errors in the article, you can put forward and grow together.

GitHub:https://github.com/mingyang66/spring-parent/blob/master/spring-common-service/beanpostprocessor.md

Topics: Spring github Attribute