spring source 17: initialization

Keywords: Spring Attribute Java

Before this article, if readers are not familiar with beaaware and BeanPostProcessors, it is strongly recommended to read this article first: spring BeanPostProcessor lifecycle

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {
		...
		try {
			//
			/**
			 * 4. Fill attribute
			 * If @ Autowired annotation attribute is used, after parsing at the top, inject here
			 *
			 * @Autowired
			 * private Inner inner;
			 */
			populateBean(beanName, mbd, instanceWrapper);
			// 5. initialization
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		...
}

Initialize bean

	protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				// 1. Callback the set methods of various kinds of Aware to realize injection
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			// Callback the set methods of various kinds of Aware to realize injection
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			// 2. Application initialization preprocessing
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			// 3. Trigger custom initialization 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()) {
			// 4. Post processing of application initialization
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}
  1. spring can obtain the corresponding information from the write set method by inheriting various beaaware.
    Take BeanNameAware for example:
	private void invokeAwareMethods(final String beanName, final Object bean) {
		if (bean instanceof Aware) {
			// Bean implements BeanNameAware, calls back the subclass setBeanName method, and returns beanName to bean for assignment
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			// Bean implements BeanClassLoaderAware, calls back the subclass setBeanClassLoader method, and returns the bean class loader to the bean for assignment
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			// Bean implements BeanFactoryAware, calls back the subclass setBeanFactory method, and returns the current BeanFactory to bean for assignment
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

When spring detects that the current bean inherits beannaware, it calls ((beannaware) bean). Setbeanname (beanName); to pass in beanName, which is implemented by a subclass. In fact, it calls the following code to assign beanName to a subclass, and BeanFactoryAware does the same

public class A implements BeanNameAware {
	private String beanName;

	@Override
	public void setBeanName(String name) {
		this.beanName = name;
		System.out.println("BeanNameAware Be called, Acquired beanName: " + name);
	}
}
  1. Instantiation preprocessing
    Postprocessing has been introduced a lot, that is, calling the postProcessBeforeInitialization method of the corresponding subclass to modify the bean, which will not be discussed here. It should be noted that the postprocessor here is a little different, that is, there is an Object current object, which means that after instantiation and preprocessing, the incoming bean may be modified to other beans. The value here is not only the content modification, but also the physical address modification, which will lead to the failure of the pre exposure object, and then cause the problem of the dependent object.
    At this point, we spring source 12: spring creates Bean Point 6 of has been introduced. At that time, you can understand it. Now you can go back and study it again
	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			// Call initialization preprocessor
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}
  1. Trigger custom initialization method
    In the spring startup phase, the init method attribute has been resolved and saved to BeanDefinition. Now, what we need to do is to take out the method name in BeanDefinition and trigger the initialization method by reflection
	protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {

		// If the bean implements 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>) () -> {
						// The afterpropertieset method of callback bean customization
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				// The afterpropertieset method of callback bean customization
				((InitializingBean) bean).afterPropertiesSet();
			}
		}

		// Initialization current bean is not empty
		if (mbd != null && bean.getClass() != NullBean.class) {
			// Init method method for spring start-up parsing
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
				// Trigger initialization method by reflection
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}
  1. Initialize postprocessing
    There will be no more introduction about the post processor. You can refer to the initialization pre-processing. The same points need to be noted

If you see here, congratulations to you that the source code of spring Ioc container has been read. The source code of spring needs to be read repeatedly to be understood. Every time you read the source code, you will get new insights. We encourage you to look back and be hammered several times. After all, this is the most powerful architecture in JAVA. It's not too much to say that it's the wisdom of Minoan!

Published 29 original articles, won praise 5, visited 6335
Private letter follow

Posted by benjaminbeazy on Fri, 13 Mar 2020 22:58:04 -0700