I believe we are familiar with the life cycle of SpringBean. Even if we have not had a comprehensive understanding of it, we believe we have dabble in it by looking at some high-frequency test sets. As follows:

In the previous article, we mentioned that we can provide custom control over beans by extending the BeanFactoryPostProcessor interface, which allows us to change the definition of the bean, imagine modifying the class file so that every instantiated object changes. We can also change only the specific instantiated object, which is done through the BeanPostProcessor interface.

1. Source code analysis

How is the implementation class of BeanPostProcessor registered with the Spring container

Also, continue to return to the origin of all things – AbstractApplicationContext refresh method

	public void refresh(a) throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory); .Copy the code

As shown in the code, registerBeanPostProcessors method is responsible for the BeanPostProcessor implementation class to register into the container. Continue to track, you can see registerBeanPostProcessors method is given to PostProcessorRegistrationDelegate class

public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
		// 1. Get the name of the Bean registered in the container, according to the BeanDefinition BeanName
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true.false);

		 // 2. The total number of BeanPostProcessors added by the addBeanPostProcessor method and the number of BeanPostProcessors registered in the container
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    // 3. Add a BeanPostProcessorChecker, mainly for logging
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// save the postprocessor that implements both BeanPostProcessor and PriorityOrdered interfaces
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    	/ / save the rear MergedBeanDefinitionPostProcessor interface of the processor
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
    	// Saves the name of the postprocessor that implements both the BeanPostProcessor and Ordered interface
		List<String> orderedPostProcessorNames = new ArrayList<>();
    	// Save the name of the post-processor that implements both BeanPostProcessor and no sort interface
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    	// 4. Iterate over all the post-processor names and put them into the different collections declared above according to their types
        // A post-processor that implements the PriorityOrdered interface will also be created
        / / if implemented MergedBeanDefinitionPostProcessor interface, into the internalPostProcessors
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				if (pp instanceofMergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); }}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else{ nonOrderedPostProcessorNames.add(ppName); }}/ / priorityOrderedPostProcessors collection sorting and priorityOrderedPostProcessors rear of a set of processors are added to the container
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// 7. Iterate over the names of all postordered processors that implement the Ordered interface and create them. If implemented MergedBeanDefinitionPostProcessor interface, into the internalPostProcessors
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceofMergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); }}// Sort and add it to the container
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		/ / 7. Traverse all realized the regular post processor (don't implement any sort interface) name, and to create, if realized MergedBeanDefinitionPostProcessor interface, into the internalPostProcessors
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceofMergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); }}// 8. Note that regular post-processors do not call sortPostProcessors for sorting
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// 9. Sort internalPostProcessors and add them to the container
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		/ / create a ApplicationListenerDetector object and registered with the container, mainly in order to can detect all the event listener, this is the front when calculating the value of beanProcessorTargetCount plus one of the reasons
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}
Copy the code

The main process is annotated, so there’s not much to read. But need to be clear, you can see, at the end of the program to internalPostProcessors this queue sorting and injection, and before that, the registerBeanPostProcessors method has been called many times, beans were repeatedly injected wouldn’t happen? Also, to answer this question, we need to look at the inside of the registerBeanPostProcessors method processing logic:

	private static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, List
       
         postProcessors)
        {

		for(BeanPostProcessor postProcessor : postProcessors) { beanFactory.addBeanPostProcessor(postProcessor); }}Copy the code

AbstractBeanFactory addBeanPostProcessor

	@Override
	public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
		Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
		// Remove from old position, if any
		this.beanPostProcessors.remove(beanPostProcessor);
		// Track whether it is instantiation/destruction aware
		if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
			this.hasInstantiationAwareBeanPostProcessors = true;
		}
		if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
			this.hasDestructionAwareBeanPostProcessors = true;
		}
		// Add to end of list
		this.beanPostProcessors.add(beanPostProcessor);
	}
Copy the code

As you can see, it is deleted before it is added, so that repeated registration will not be a problem.

How is the implementation class of the registered BeanPostProcessor used

Or AbstractApplicationContext refresh method

public void refresh(a) throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
            	......
				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory); .Copy the code

FinishBeanFactoryInitialization way shown above is responsible for the instantiation and initialization of the bean, and in this process have the BeanPostProcessor implementation class used logic, but given the middle have multilayer logic and calls, limited space not much, Look directly at the stack information

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean()
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean()
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean()
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject()
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton()
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean()
org.springframework.beans.factory.support.AbstractBeanFactory.getBean()
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons()
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization()
org.springframework.context.support.AbstractApplicationContext.refresh()
org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh()
org.springframework.boot.SpringApplication.refresh()
org.springframework.boot.SpringApplication.refreshContext()
org.springframework.boot.SpringApplication.run()
Copy the code

Check AbstractAutowireCapableBeanFactory class initializeBean () method

	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 {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null| |! mbd.isSynthetic()) {// For instantiated beans, use the BeanPostProcessor implementation class before initialization
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
             // Initialize the bean
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw newBeanCreationException( (mbd ! =null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null| |! mbd.isSynthetic()) {// For instantiated beans, use the BeanPostProcessor implementation class after initialization
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}
Copy the code

Obviously, applyBeanPostProcessorsBeforeInitialization and applyBeanPostProcessorsAfterInitialization method is what we need to focus on, look at these two methods, logic is very simple, Is the removal of all registered is BeanPostProcessor implementation class, perform its postProcessBeforeInitialization and postProcessAfterInitialization method, The input parameter is the bean instance that is currently being instantiated and initialized

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

Copy the code
	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;
	}
Copy the code

That’s how the Spring container calls the implementation class of BeanPostProcessor.

2. Practice

Again, use the User class we created in the last article

@Component
public class User {

    private String name = "AAA";

    public String getName(a) {
        return name;
    }

    public void setName(String name) {
        this.name = name; }}Copy the code

Custom implementation class for BeanPostProcessor

@Component
public class CustomizeBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if("user".equals(beanName)) {
            User user = (User)bean;
            user.setName("BBB");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if("user".equals(beanName)) {
            User user = (User)bean;
            System.out.println(user.getName());
        }
        returnbean; }}Copy the code

Start the program, and you can see the console output “BBB,” indicating that the goal of controlling the bean instance has been achieved.