什么是BeanPostProcessor接口?

spring BeanPostProcessor接口可以在Bean初始化操作之前和初始化操作之后做一些有趣的事情。例如属性注入(AutowiredAnnotationBeanPostProcessor

例如AOP代理类生成(AnnotationAwareAspectJAutoProxyCreator

总之,他的作用是非常大,能适应的场景也是非常多。

BeanPostProcessor系的接口列表

接口列表

BeanPostProcessor

InstantiationAwareBeanPostProcessor

SmartInstantiationAwareBeanPostProcessor

该系列接口都是在BeanPostProcessor基础上扩展,只是某些方法产生了细分,大方向上与BeanPostProcessor一致。

为什么会失效?

失效原因1:BeanPostProcessor不是Bean或注册为Bean的时机不对

public class Bean3 {
}


public class BeanPostProcessorDemo implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName+"初始化之前");
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName+"初始化之后");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

//有输出示例
public static void main( String[] args )
{

AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();

        ac.register(Bean3.class);
        ac.register(BeanPostProcessorDemo.class);
        ac.refresh();
        ac.getBean(Bean3.class);   //运行有输出,一切正常
}

//无输出示例
public static void main( String[] args )
{

AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();

        ac.register(Bean3.class);
        ac.refresh(); //容器初始化
        ac.register(BeanPostProcessorDemo.class); //在容器初始化之后注册bean

        ac.getBean(Bean3.class); //运行无输出,时机已过,即使注册为Bean也无效

        
}

失效原因2:没有添加

//代码接上例
//新获取一个Bean,测试是否有效
public static void main( String[] args )
{



        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();

        ac.register(Bean3.class);
        ac.refresh();
        ac.register(BeanPostProcessorDemo.class);

        //新注册然后再获取一个bean来测试,因为Bean3被容器初始化了,但是BeanPostProcessor还没注册
        //可能是这个原因导致的。所以开启一个新的Bean来测试

        ac.register(Bean4.class);
        Object o = ac.getBean(Bean4.class); 
        //新注册一个bean,在获取 还是无输出,证明BeanPostProcessor要运行可能不仅是要求为Bean
        //可能还有其他的要求

}

//最终示例
public static void main( String[] args )
{



        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();

        ac.register(Bean3.class);
        ac.refresh();
        ac.register(BeanPostProcessorDemo.class);

    //添加BeanPostProcessor到集合中
   ac.getBeanFactory().addBeanPostProcessor(ac.getBean(BeanPostProcessorDemo.class));

        ac.register(Bean4.class);
        Object o = ac.getBean(Bean4.class);
        //有输出,证明BeanPostProcessor要运行的关键是需要追加addBeanPostProcessor方法内
        

}

BeanPostProcessor初始化,运行解析

初始化原理

//AbstractApplicationContext.java
public void refresh() throws BeansException, IllegalStateException {
    //省略若干行
    registerBeanPostProcessors(beanFactory);
    //省略若干行
}

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

        //获取所有BeanPostProcessor的Bean
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

        //省略若干行代码

        //把遍历到的BeanPostProcessor添加到集合中,至此,BeanPostProcessor初始化完毕
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		//省略若干行代码
}

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

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

运行原理

//AbstractAutowireCapableBeanFactory.java
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

        //运行原理就非常简单了,任何获取Bean的操作,都会执行
        //其中getBeanPostProcessors()方法用来获取addBeanPostProcessor的集合
        //然后就是一个遍历责任链了。从这里一个侧面可以看出,如果能实例化后添加到
        //addBeanPostProcessor方法内,那么不是Bean也是OK的。
		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
}

结论

如果初始化时机不正确,则需要手动矫正一下(通过addBeanPostProcessor方法来追加)

为什么要产生BeanPostProcessor初始化时机不对的情况,这样的场景为什么会发生?

其实这样的例子比比皆是,不是所有Bean都能在spring 容器初始化之前确定。

如果BeanPostProcessor是动态注册的,或者其他Bean也是动态注册的,则需要这样处理。很多时候,bean都是通过编程动态产生的。例如要根据远程配置文件的信息,动态生成数据库连接池Bean等等。这些场景都真实存在。