• Spring - InstantiationAwareBeanPostProcessor 扩展接口


    在这里插入图片描述


    Pre

    Spring Boot - 扩展接口一览

    在这里插入图片描述


    org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor

    在这里插入图片描述

    注意下: Initialization 表示 初始化 (意思是对象已经生成) 。 Instantiation 表示 实例化 (意思是对象还未生成) 。

    接口继承了BeanPostProcess接口 , 从方法上我们也可以看出 InstantiationAwareBeanPostProcessor 做了一些扩展 。

    BeanPostProcess接口只在bean的初始化阶段进行扩展(注入spring上下文前后),而InstantiationAwareBeanPostProcessor接口在此基础上增加了3个方法,使得扩展接口可以在实例化阶段和属性注入阶段

    该类主要的扩展点有以下5个方法,主要在bean生命周期的两大阶段:实例化阶段 和初始化阶段

    (1)实例化: 实例化的过程是一个创建Bean的过程,即调用Bean构造函数,单例的Bean入单例池中

    (2)初始化: 初始化的过程是一个赋值的过程,即调用Bean的setter方法,设置Bean属性

    InstantiationAwareBeanPostProcessor作用于过程(1)实例化前后; BeanPostProcessor用于过程(2)初始化前后


    按调用顺序,我们来看一下

    • postProcessBeforeInstantiation:实例化bean之前,相当于new这个bean之前
    • postProcessAfterInstantiation:实例化bean之后,相当于new这个bean之后
    • postProcessPropertyValues: bean已经实例化完成,在属性注入时阶段触发, @Autowired,@Resource等注解原理基于此方法实现
    • postProcessBeforeInitialization:初始化bean之前,相当于把bean注入spring上下文之前
    • postProcessAfterInitialization:初始化bean之后,相当于把bean注入spring上下文之后

    InstantiationAwareBeanPostProcessor 注册过程源码分析

    我们还是从

    org.springframework.context.support.AbstractApplicationContext#refresh
    
    • 1

    开始看 ,主要是下面两个方法

    .......
    // Register bean processors that intercept bean creation.
    registerBeanPostProcessors(beanFactory);
    
    .......
    
    // Instantiate all remaining (non-lazy-init) singletons.
    finishBeanFactoryInitialization(beanFactory);
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    看下调用栈

    org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors()
    	BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
    		org.springframework.beans.factory.support.AbstractBeanFactory#getBean
    		  org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean	
    			  org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
    
    • 1
    • 2
    • 3
    • 4
    • 5

    createBean跟进去

    @Override
    	protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
    	// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    			if (bean != null) {
    				return bean;
    			}
    	//省略....
    	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    	return beanInstance;
    
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    通过上面的代码,我们可以看到在执行doCreateBean之前有resolveBeforelnstantiation方法; 看注释

    // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    
    • 1
    • resolveBeforelnstantiation判断执行InstantiationAwareBeanPostProcessor.postProcessBeforelInstantiationg接口方法实现;
    • doCreateBean创建bean方法;

    postProcessBeforeInstantiation的执行时机源码解析

    org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors()
    	BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
    		org.springframework.beans.factory.support.AbstractBeanFactory#getBean
    		  org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean	
    			  org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
    					org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    重点看 resolveBeforeInstantiation

    	/**
    	 * Apply before-instantiation post-processors, resolving whether there is a
    	 * before-instantiation shortcut for the specified bean.
    	 * @param beanName the name of the bean
    	 * @param mbd the bean definition for the bean
    	 * @return the shortcut-determined bean instance, or {@code null} if none
    	 */
    	@Nullable
    	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    		Object bean = null;
    		//如果beforeInstantiationResolved还没有设置或者是false(说明还没有需要在实例化前执行的操作)
    		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
    			// Make sure bean class is actually resolved at this point.
    			// 判断是否有注册过InstantiationAwareBeanPostProcessor类型的bean
    			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    				Class<?> targetType = determineTargetType(beanName, mbd);
    				if (targetType != null) {
    					//执行
    					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
    					if (bean != null) {
    						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
    					}
    				}
    			}
    			mbd.beforeInstantiationResolved = (bean != null);
    		}
    		return bean;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    继续 applyBeanPostProcessorsBeforeInstantiation

    	/**
    	 * Apply InstantiationAwareBeanPostProcessors to the specified bean definition
    	 * (by class and name), invoking their {@code postProcessBeforeInstantiation} methods.
    	 * 

    Any returned object will be used as the bean instead of actually instantiating * the target bean. A {@code null} return value from the post-processor will * result in the target bean being instantiated. * @param beanClass the class of the bean to be instantiated * @param beanName the name of the bean * @return the bean object to use instead of a default instance of the target bean, or {@code null} * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation */ @Nullable protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) { // 循环处理 for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { Object result = bp.postProcessBeforeInstantiation(beanClass, beanName); //只要有一个result不为null;后面的所有 后置处理器的方法就不执行了,直接返回(所以执行顺序很重要) if (result != null) { return result; } } return null; }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    当然了也有 postProcessAfterInitialization

    	@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;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    使用场景 : 创建代理类

     package com.artisan.bootspringextend.testextends;
    
    import com.artisan.bootspringextend.service.ArtisanServiceImpl;
    import com.artisan.bootspringextend.service.ClassA;
    import com.artisan.bootspringextend.service.ClassAInterceptor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.PropertyValues;
    import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @author 小工匠
     * @version 1.0
     * @description:
     * @date 2022/11/28 0:33
     * @mark: show me the code , change the world
     */
    
    @Slf4j
    @Configuration
    public class ExtendInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    
        private static final String VALUE = "classA";
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
            if (VALUE.equals(beanName)) {
                log.info("4  beanName {}-----> postProcessBeforeInitialization", beanName);
    
            }
            return bean;
        }
    
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (VALUE.equals(beanName)) {
                log.info("5   beanName {}-----> postProcessAfterInitialization", beanName);
    
            }
    
            return bean;
        }
    
        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    
    
            if (beanClass == ClassA.class) {
                log.info("1  beanName {} -----> postProcessBeforeInstantiation", beanName);
    
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(beanClass);
                enhancer.setCallback(new ClassAInterceptor());
    
                ClassA classA = (ClassA) enhancer.create();
                log.info("proxy created ---->{}", classA.toString());
    
                return classA;
            }
    
            return null;
        }
    
    
        @Override
        public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    
            if (VALUE.equals(beanName)) {
                log.info("2   beanName {}-----> postProcessAfterInstantiation", beanName);
    
            }
    
            return false;
        }
    
    
        @Override
        public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
    
            if (VALUE.equals(beanName)) {
                log.info("3   beanName {} -----> postProcessProperties", beanName);
    
            }
            return pvs;
        }
    }
        
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    在这里插入图片描述

    我们可以看到 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 生成了代理类后,直接执行了 初始化后的动作 BeanPostProcessor#postProcessAfterInitialization

    在这里插入图片描述

  • 相关阅读:
    Lnmp架构之mysql数据库实战1
    直播回顾|7 月 Pulsar 中文开发者与用户组会议
    LeetCode——贪心篇(三)
    SQL Server数据库创建远程服务器备份计划(小白详细图文教程)
    ChatGPT调教指南 | 咒语指南 | Prompts提示词教程(二)
    idea中把spring boot项目打成jar包
    使用Pytorch实现深度学习的主要流程
    微服务技术栈-认识微服务和第一个微服务Demo
    【vxe-table】加载渲染列表数据的写法以及一些相关的常用属性
    场景之多数据源查询及数据下载问题
  • 原文地址:https://blog.csdn.net/yangshangwei/article/details/128066539