Spring BeanPostProcessor理解和使用原理分析

基础

如果使用过Spring,写过项目,那么一定了解IOC容器,Bean校验,@Autowired依赖注入这些,其实内部很多实现,都是通过BeanPostProcessor来实现

BeanPostProcessor 作用:

初始化Bean前后做一些赋值,解析处理相关操作

BeanPostProcessor接口

public interface BeanPostProcessor {

	/**
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one;
	 * if {@code null}, no subsequent BeanPostProcessors will be invoked
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
	 */
	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

	/**
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one;
	 * if {@code null}, no subsequent BeanPostProcessors will be invoked
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
	 * @see org.springframework.beans.factory.FactoryBean
	 */
	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

我们只需要实现该接口,标注@Bean注入容器,容器在创建该Bean实例后,调用对应的BeanPostProcessor进行相关处理

对应的实现类,这里标注了一部分常用的
在这里插入图片描述

我们这里以实际案例为切入点,进行切入分析

ApplicationContextAwareProcessor

我们开发中,特别是多模块开发中,对于有些模块不需要Spring,因此往往不会给这个模块导入Spring依赖,该模块也就无法获取IOC容器。

但是有时,我们又需要IOC容器,获取其中的Bean,Environment。往往定义一个工具类模块,定义一个Bean实现ApplicationContextAware接口,往其中注入IOC容器,最后通过静态方法,其它模块也可以获取IOC容器了

ApplicationContextAwareProcessor源码

class ApplicationContextAwareProcessor implements BeanPostProcessor {

	private final ConfigurableApplicationContext applicationContext;

	private final StringValueResolver embeddedValueResolver;


	/**
	 * Create a new ApplicationContextAwareProcessor for the given context.
	 */
	public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
		this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
	}


	@Override
	public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
		AccessControlContext acc = null;

		if (System.getSecurityManager() != null &&
				(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
						bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
						bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged(new PrivilegedAction<Object>() {
				@Override
				public Object run() {
					invokeAwareInterfaces(bean);
					return null;
				}
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
			}
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		return bean;
	}

}

测试

获取IOC容器的类

public class IOCUtil implements ApplicationContextAware {


    private  ApplicationContext applicationContext;


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }


    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }
}

主配置类

@Configuration
public class MainConfig {

    @Bean
    public IOCUtil iocUtil(){
        return new IOCUtil();
    }

}

测试方法和结果

@Test
    public  void test02(){
        AnnotationConfigApplicationContext applicationContext = new
                AnnotationConfigApplicationContext(MainConfig.class);

        IOCUtil iocUtil = applicationContext.getBean(IOCUtil.class);

        System.out.println(iocUtil.getApplicationContext());
        System.out.println(applicationContext);

        applicationContext.close();
    }

在这里插入图片描述

可以看到通过实现ApplicationContextAware,然后将Bean放入IOC容器,IOC容器创建Bean实例后,自动通过对应方法将IOC容器传送过来保存。此时两个IOC容器对象一样,说明是同一个

那么怎么实现的呢???

1、创建容器
在这里插入图片描述

2、调用reFresh,刷新容器

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			
			.........省略部分不重要源码
			
			# 为上下文准备BeanFactory			
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			prepareBeanFactory(beanFactory);

			try {
				
				postProcessBeanFactory(beanFactory);

				
				# 调用BeanPostProcessor,扫描组件,生成BeanDefinitioninvokeBeanFactoryPostProcessors(beanFactory);

				## 注册准备BeanPostProcessors默认七个
				registerBeanPostProcessors(beanFactory);
				

				## 通过BeanDefinition创建Bean实例,通过注册的BeanPostProcessorBean init,属性赋值,进行前后处理
				finishBeanFactoryInitialization(beanFactory);


			}
		}
	}

BeanDefinitionMap

在这里插入图片描述

BeanPostProcessors默认七个
在这里插入图片描述

走到这里BeanPostProcessors已经全部创建完毕,只等InitBean时候进行调用

3、finishBeanFactoryInitialization(beanFactory); 生成实例,初始化Bean示例

通过BeanDefinition创建Bean实例,通过注册的BeanPostProcessor对Bean init,属性赋值,进行前后处理
finishBeanFactoryInitialization(beanFactory);

生成实例流程(默认没有,会创建)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

doGetBean中的
在这里插入图片描述

在这里插入图片描述

bean默认不存在,通过BeanDefinition,会创建的
在这里插入图片描述

在这里插入图片描述

此时Bean已经创建完成(底层是通过反射+动态代理实现,有兴趣可以自行查看源码)populateBean为bean赋属性值,

Bean创建完成并属性赋值之后,对Bean进行初始化
在这里插入图片描述
在这里插入图片描述
显然我们IOCUtil实现ApplicationContextAware接口

在这里插入图片描述
可惜的是我们并没有实现BeanFactoryAware这样的接口,因此无法调用,SetBeanFactoryAware的方法,无法获取BeanFactory容器

在这里插入图片描述
调用BeanPostProcessorsBeforeInitialization

在这里插入图片描述
在这里插入图片描述

获取默认注册过的BeanPostProcessor,默认七个

ApplicationContextAwareProcessor

class ApplicationContextAwareProcessor implements BeanPostProcessor {

	private final ConfigurableApplicationContext applicationContext;

	private final StringValueResolver embeddedValueResolver;



	@Override
	public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
		AccessControlContext acc = null;

		if (System.getSecurityManager() != null &&
				(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
						bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
						bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged(new PrivilegedAction<Object>() {
				@Override
				public Object run() {
					invokeAwareInterfaces(bean);
					return null;
				}
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
			}
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		return bean;
	}

}

在这里插入图片描述
找到Bean实现的Aware接口
在这里插入图片描述

由于我们实现ApplicationContextAware,向上转型,为Bean设置ApplicationContext

在这里插入图片描述
最终走到了我们自定义的Bean中,保存applicationContext,因此Bean获取到了applicationContext

注意:如果我们想获取ApplicationContext,Beanfactory,Environment等等,可以实现这些Aware接口,在initialBean时候,通过XXXAwareProcessor(BeanPostProcessor)进行设值保存

在这里插入图片描述

PostProcessorBeforeInitialization走完后,会走 initBean

在这里插入图片描述

initBean走完后,会走PostProcessorAfterInitialization
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白鸽呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值