所有分类
  • 所有分类
  • 未分类

Spring–BeanPostProcessor–作用/介绍

简介

说明

本文介绍Spring中BeanPostProcessor的作用

所有的Bean都会走到BeanPostProcessor接口的postProcessBeforeInitialization和postProcessAfterInitialization方法。

Spring的Bean的生命周期流程见:Spring-Bean生命周期-流程/原理 – 自学精灵

流程

 AbstractApplicationContext#refresh()
    registerBeanPostProcessors(beanFactory) //AbstractApplicationContext
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
            BeanPostProcessor pp = (BeanPostProcessor)beanFactory.getBean(ppName, BeanPostProcessor.class);
                getBean(String name, Class<T> requiredType)   //AbstractBeanFactory
                    doGetBean(name, requiredType, null, false) //AbstractBeanFactory
                        createBean(beanName, mbd, args); //AbstractAutowireCapableBeanFactory
                            doCreateBean(beanName, mbdToUse, args);  //AbstractAutowireCapableBeanFactory

BeanPostProcessor的加载顺序

简介

说明

Spring容器启动过程,从向容器注册BeanPostProcessor这一步开始说明: 

final class PostProcessorRegistrationDelegate {
	public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, 
                                                 AbstractApplicationContext applicationContext) {
	
		// 注意:此处只会拿到Bean的定义信息。
		// 已被实例化的Bean最终都会调用`beanFactory.addBeanPostProcessor`,把这些bean缓存
        //     在AbstractBeanFactory的字段beanPostProcessors里,它是个CopyOnWriteArrayList,最终
        //     所有BeanPostProcessor都会从这个List里面拿出来执行。
		// 本方法的作用是:按顺序,把`BeanPostProcessor`们实例化,然后添加进List。
		//     因此顺序是关键:若某些Bean提前被实例化,它就很可能不能被所有的`BeanPostProcessor`处理到了
		//     (这也是BeanPostProcessorChecker的作用:检查这个然后输出日志的)
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);


		// beanProcessorTargetCount此处赋值后,后续就都不会变了,BeanPostProcessorChecker就是和这个进行比较的。
		// beanProcessorTargetCoun = beanFactory里面的Bean实例总个数 + 1(自己)+ bean定义信息~
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		
        // 把BeanPostProcessorChecker加进去。它其实做了一个检查而已:输出一个info日志
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
		
		// 1、找到同时实现BeanPostProcessor和PriorityOrdered的bean=> getBean=> 排序=> beanFactory.addBeanPostProcessor()
		// 2、找到同时实现BeanPostProcessor和Ordered的bean,后续步骤同上
		// 3、处理没实现排序接口的普通的处理器,不需要sort了,直接add进去。
        // 此处代码很多,直接省略。上边三行即描述的此处代码的功能
	
		// 注册一个特殊的处理器
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}
}

代码追踪

写一个自己的后置处理器

package com.example.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

@Component
public class MyProcessor implements BeanPostProcessor, Ordered {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization==> " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization==> " + beanName);
        return bean;
    }
}

打断点、启动SpringBoot,

  1. AutowiredAnnotationBeanPostProcessor它实现了PriorityOrdered接口
    1. 处理@Autowired,@Value,@Inject
  2. CommonAnnotationBeanPostProcessor它也实现了PriorityOrdered接口
    1. 处理@Resource、@PostConstruct、@PreDestroy。
  3. AsyncAnnotationBeanPostProcessor没有实现任何Orderd排序接口
  4. MyProcessor此处我们让它实现了Ordered接口

总结

1.自定义的BeanPostProcessor实现类有时可以有时不可以@Autowired来注入一个bean

可以的情况

自定义的BeanPostProcessor实现类没实现顺序接口,或者实现了Ordered接口。而AutowiredAnnotationBeanPostProcessor会负责处理@Autowired,AutowiredAnnotationBeanPostProcessor实现的是靠前的PriorityOrdered,它比没实现顺序接口,或者实现了Ordered接口的后置处理器要实例化的早,所以等到处理到这里的自定义BeanPostProcessor实现类时,可以成功@Autowired来注入一个bean,

不可以的情况

自定义的BeanPostProcessor实现类实现了PriorityOrdered接口。

2.自己定义的BeanPostProcessor实现类可以通过实现ApplicationContextAware接口获得bean

因为这个接口是被ApplicationContextAwareProcessor来解析的,而它已经早早被放进了Spring容器里面,所以通过实现接口的方式任何时候都是可以的。

BeanPostProcessorChecker

BeanPostProcessorChecker是一个BeanPostProcessor,是PostProcessorRegistrationDelegate的一个private static内部类,它的作用就是在postProcessAfterInitialization里检查作用在此Bean上的BeanPostProcessor够不够数,如果不够数(一般是提前加载了,或者被auto-proxying了这种情况就输出一条info日志)。日志示例:trationDelegate$BeanPostProcessorChecker : Bean ‘myBean’ of type [com.example.processor.MyBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

final class PostProcessorRegistrationDelegate {
	private static final class BeanPostProcessorChecker implements BeanPostProcessor {

		private static final Log logger = LogFactory.getLog(BeanPostProcessorChecker.class);

		// 从if条件可以看出哪些是不需要检测的Bean
		// 1、BeanPostProcessor类型不检测
		// 2、ROLE_INFRASTRUCTURE这种类型的Bean不检测 (Spring自己的Bean)
		@Override
		public Object postProcessAfterInitialization(Object bean, String beanName) {
			if (!(bean instanceof BeanPostProcessor) && !isInfrastructureBean(beanName) &&
					this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount) {
				if (logger.isInfoEnabled()) {
					logger.info("Bean '" + beanName + "' of type [" + bean.getClass().getName() +
							"] is not eligible for getting processed by all BeanPostProcessors " +
							"(for example: not eligible for auto-proxying)");
				}
			}
			return bean;
		}

		private boolean isInfrastructureBean(@Nullable String beanName) {
			if (beanName != null && this.beanFactory.containsBeanDefinition(beanName)) {
				BeanDefinition bd = this.beanFactory.getBeanDefinition(beanName);
				return (bd.getRole() == RootBeanDefinition.ROLE_INFRASTRUCTURE);
			}
			return false;
		}
	}
    // 其他代码
}
0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录