Spring的9处调用后置处理器

编程入门 行业动态 更新时间:2024-10-28 12:16:57

Spring的9处调用后置<a href=https://www.elefans.com/category/jswz/34/1768090.html style=处理器"/>

Spring的9处调用后置处理器

在Sping的整个生命周期中,有9个地方调用后置处理器。这些后置处理器是spring实现自定义功能或者扩展spring的核心所在

一、实例化前

该方法属于InstantiationAwareBeanPostProcessor后置处理器

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {@Nullabledefault Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {return null;}default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}@Nullabledefault PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)throws BeansException {return null;}@Deprecated@Nullabledefault PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {return pvs;}}

该方法的意思其实也体现到名字上了,就是在实例化之前做些什么。
如果该方法返回非空,代表整个创建流程提前结束,也就是说后面什么属性设置,bean的初始化等等都不会执行了,所以重写该方法一定要谨慎。这个方法一般会和 applyBeanPostProcessorsAfterInitialization后置结处理器结合使用,这个处理可是实现aop的核心,这个后面在分析。

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {Object bean = null;if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {// Make sure bean class is actually resolved at this point.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;}

因为如果你在applyBeanPostProcessorsBeforeInstantiation中返回非空后,后面spring的流程就不会走了,但是如果你有个切面是想代理这个类,那就没有办法了,所以applyBeanPostProcessorsBeforeInstantiation返回非空后会调用applyBeanPostProcessorsAfterInitialization执行aop代理

至于网上说的说法:

如果这里出现了aop的切面类,就会有InstantiationAwareBeanPostProcessor的子处理器进行类的过滤,出现@AspectJ的类标记为不需要代理的类,会被放入map中

我目前不理解,我自己写了一个切面类,结果还是和正常类走相同的流程。

二、实例bean前决定构造器

createBeanInstance中的方法determineConstructorsFromBeanPostProcessors中会调用SmartInstantiationAwareBeanPostProcessor 后置处理器的determineCandidateConstructors方法。

2.1 SmartInstantiationAwareBeanPostProcessor


该构造器主要就是为了预测最终bean的类型(predicting the eventual type of a processed bean)。

2.2 determineCandidateConstructors

该方法也是此处构造器的真正要做的事情。就是为了决定实例化bean的构造器

private DeptService service;public DeptController(@Autowired DeptService service){this.service = service;
}

比如这种情况,肯定不走默认的构造函数,spring就会在determineCandidateConstructors中决定出这个有参数的构造器,然后创建实例的时候回检查参数是否有@Autowired的,在构造的时候就会把service给创建好

三、刚创建好实例之后

createBeanInstance之后,这个时候bean的属性、初始化方法等等都没有创建好,基本属于空白对象。然后在方法applyMergedBeanDefinitionPostProcessors中执行类MergedBeanDefinitionPostProcessor的后置处理

3.1 MergedBeanDefinitionPostProcessor


这个类主要用来更改或者丰富bean的定义的元数据信息。

3.2 方法postProcessMergedBeanDefinition

  1. CommonAnnotationBeanPostProcessor:这个是MergedBeanDefinitionPostProcessor 一个重要的子类,在这个类中
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);//主要记录生命周期方法InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);//记录@Resource  metadatametadata.checkConfigMembers(beanDefinition);}

可见主要是为了后面的流程进行的一些辅助动作。

  1. AutowiredAnnotationBeanPostProcessor:另外一个重要的子类。
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);//记录@AutoWired medatametadata.checkConfigMembers(beanDefinition);}

还是为了后面的流程进行的一些辅助动作。

四、解决循环依赖

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {Object exposedObject = bean;if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);}}}return exposedObject;}

上面这段源码是在创建好bean后,如果开启了循环依赖,那么会执行

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

这个时候就来到了主角 getEarlyBeanReference这里。

可见该后置处理器属于SmartInstantiationAwareBeanPostProcessor,这里到底是做什么呢?

4.1 AbstractAutoProxyCreator

改具体子类实现了SmartInstantiationAwareBeanPostProcessor接口。

public Object getEarlyBeanReference(Object bean, String beanName) {Object cacheKey = getCacheKey(bean.getClass(), beanName);this.earlyProxyReferences.put(cacheKey, bean);return wrapIfNecessary(bean, beanName, cacheKey);}

这个代码就是返回aop代码的代码。 所以该后置处理器有个功能就是返回aop的代理

五、实例化后

在属性填充方法populateBean

if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {continueWithPropertyPopulation = false;break;}}}}

改后置处理器来自InstantiationAwareBeanPostProcessor,调用其中的postProcessAfterInstantiation
改方法功能也简单,就是判断是否进行属性注入。

六 设置属性前

for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}}

改后置处理器用在 在工厂将给定的属性值应用到给定bean之前,对给定的属性值进行后处理。你可以进行一些检查,比如某个属性是 “required”的,但是这个属性需要的引用却是空,这个时候可以进行一些检查工作。还有dubbo的注解 @DubboReference这个注解,就是在此处 替换需要注入的类来实现的。

七 执行初始化方法前

if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}

改代码是在方法initializeBean中调用的。applyBeanPostProcessorsBeforeInitialization详细调用是

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

可以看到他的引用是接口BeanPostProcessor这个接口属于顶级接口,他的子类太多了,其中有个出名的是CommonAnnotationBeanPostProcessor 该类的结构图是

其中他的父类InitDestroyAnnotationBeanPostProcessor是个重点角色,在改类中的postProcessBeforeInitialization方法中就执行了大名鼎鼎的 @PostConstruct 注解的方法。

八 执行初始化方法后

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

鼎鼎大名的aop就是在这里进行实现的。具体的后置处理器是AbstractAutoProxyCreator

九 销毁bean容器的时候调用

具体后置处理器InitDestroyAnnotationBeanPostProcessor

然后调用的方法是postProcessBeforeDestruction

public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());try {metadata.invokeDestroyMethods(bean, beanName);}catch (InvocationTargetException ex) {String msg = "Destroy method on bean with name '" + beanName + "' threw an exception";if (logger.isDebugEnabled()) {logger.warn(msg, ex.getTargetException());}else {logger.warn(msg + ": " + ex.getTargetException());}}catch (Throwable ex) {logger.warn("Failed to invoke destroy method on bean with name '" + beanName + "'", ex);}}

什么是destory方法呢,被javax.annotation.PreDestroy 注解的的方法。

更多推荐

Spring的9处调用后置处理器

本文发布于:2023-07-03 07:56:21,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1003450.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:处理器   Spring

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!