Initializing Bean, init-method and PostConstruct initialized by Spring Bean

Keywords: Spring Apache React Attribute

InitializingBean knows from the name of the interface that its function is to perform customized operations after the bean is initialized.

Beans in Spring containers have a life cycle. Spring allows specific operations to be performed after Bean initialization and before Bean destruction. There are three long-term settings:

    1. By implementing InitializingBean/Disposable Bean interface, customize the operation method after initialization/before destruction;
    2. The init-method/destroy-method attribute of the < bean > element specifies the operation method invoked after initialization/before destruction.
    3. Add @PostConstruct or @PreDestroy annotations to the specified method to determine whether the method is invoked after initialization or before destruction.

The source code of initializing bean interface is as follows:

/*
 * Copyright 2002-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory;

/**
 * Interface to be implemented by beans that need to react once all their properties
 * have been set by a {@link BeanFactory}: e.g. to perform custom initialization,
 * or merely to check that all mandatory properties have been set.
 *
 * <p>An alternative to implementing {@code InitializingBean} is specifying a custom
 * init method, for example in an XML bean definition. For a list of all bean
 * lifecycle methods, see the {@link BeanFactory BeanFactory javadocs}.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @see DisposableBean
 * @see org.springframework.beans.factory.config.BeanDefinition#getPropertyValues()
 * @see org.springframework.beans.factory.support.AbstractBeanDefinition#getInitMethodName()
 */
public interface InitializingBean {

	/**
	 * Invoked by the containing {@code BeanFactory} after it has set all bean properties
	 * and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc.
	 * <p>This method allows the bean instance to perform validation of its overall
	 * configuration and final initialization when all bean properties have been set.
	 * @throws Exception in the event of misconfiguration (such as failure to set an
	 * essential property) or if initialization fails for any other reason
	 */
	void afterPropertiesSet() throws Exception;

}

The interface has only one method, afterProperties Set, whose call entry is Abstract Autowire Capable BeanFactory, which is responsible for loading spring bean s. The source code is as follows:

/**
	 * Give a bean a chance to react now all its properties are set,
	 * and a chance to know about its owning bean factory (this object).
	 * This means checking whether the bean implements InitializingBean or defines
	 * a custom init method, and invoking the necessary callback(s) if it does.
	 * @param beanName the bean name in the factory (for debugging purposes)
	 * @param bean the new bean instance we may need to initialize
	 * @param mbd the merged bean definition that the bean was created with
	 * (can also be {@code null}, if given an existing bean instance)
	 * @throws Throwable if thrown by init methods or by the invocation process
	 * @see #invokeCustomInitMethod
	 */
	protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {

		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 {
				((InitializingBean) bean).afterPropertiesSet();
			}
		}

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

The following conclusions can be drawn from this code:

1. spring provides two ways to initialize beans. It implements Initializing bean interface and afterProperties Set side.
Method, or specified by init-method in the configuration file, can be used in both ways
 2. Implementing the InitializingBean interface is to call the afterPropertiesSet method directly, rather than calling the party specified by init-method through reflection.
The efficiency of the method is relatively high. But the init-method approach eliminates the dependence on spring
 3. Call the afterPropertiesSet first, then execute the init-method method method. If an error occurs when calling the afterPropertiesSet method,
Do not call the method specified by init-method

@ PostConstruct, which is called the class InitDestroyAnnotationBeanPostProcessor

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

From naming, we can get some information -- this is a BeanPost Processor. What comes to mind? In the life cycle of Spring containers, it was mentioned that BeanPostProcessor's postProcess BeforeInitialization was invoked before afterProperties Set and init-method in the Bean life cycle. In addition, the @PostConstruct method is also invoked through the launch mechanism through tracking.

Summarize

1. Initialization order of spring bean s: construction method - > @PostConstruct annotation method - > afterProperties Set party
 Method - > method specified by init-method. Specific examples can be used for reference.
2. After PropertiesSet is invoked through interface implementation (a little more efficient), @PostConstruct and init-method are invoked through reverse
 Launch mechanism call

 

 

 

Posted by IsmAvatar on Thu, 01 Aug 2019 02:46:06 -0700