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