BeanPostProcesser和BeanFactoryPostProcesser的理解


这段时间在仔细研读Spring的官方文档,看到了这个两个接口。文档中花了较大的篇幅介绍这两个接口。这个两个接口都属于容器扩展点类的接口, 作用是影响Bean的初始化过程,说白了就是一种AOP的思想,对Bean的初始化的过程进行“增强”

介绍

BeanPostProcessor

The BeanPostProcessor interface defines callback methods that you can implement to provide your own (or override the container’s default) instantiation logic, dependency resolution logic, and so forth. If you want to implement some custom logic after the Spring container finishes instantiating, configuring, and initializing a bean, you can plug in one or more custom BeanPostProcessor implementations. 引自:Spring.io

BeanPostProcesser 接口定义了一些回调方法,开发人员可以实现自己的Bean的实例化逻辑和依赖逻辑。如果你想要在Spring完成了对象的初始化后,实现自己的业务逻辑,你可以通过实现一个或多个BeanPostProcesser接口。

源代码:

public interface BeanPostProcessor {

	/**
         *  在Bean实例化之后,初始化之前 回调此方法
	 * Apply this {@code BeanPostProcessor} to the given new bean instance <i>before</i> any bean
	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * <p>The default implementation returns the given {@code bean} as-is.
	 * @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
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
          * 在Bean的初始化之后,回调此方法
	 * Apply this {@code BeanPostProcessor} to the given new bean instance <i>after</i> any bean
	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
	 * instance and the objects created by the FactoryBean (as of Spring 2.0). The
	 * post-processor can decide whether to apply to either the FactoryBean or created
	 * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
	 * <p>This callback will also be invoked after a short-circuiting triggered by a
	 * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
	 * in contrast to all other {@code BeanPostProcessor} callbacks.
	 * <p>The default implementation returns the given {@code bean} as-is.
	 * @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
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

BeanFactoryPostProcesser

The semantics of this interface are similar to those of the BeanPostProcessor, with one major difference: BeanFactoryPostProcessor operates on the bean configuration metadata. That is, the Spring IoC container lets a BeanFactoryPostProcessor read the configuration metadata and potentially change it before the container instantiates any beans other than BeanFactoryPostProcessor instances.
引自 Spring.io

BeanFactoryPostProcesserBeanPostProcesser是非常相似的,但是它们之间有一个主要的区别:BeanFactoryPostProcesser操作Bean的配置信息。也就是说,Spring IOC容器允许BeanFactoryPostProcess在容器实例化除了 BeanFactoryPostProcessbean以外的其他Bean的时候读取配置信息并修改它。

源代码:

@FunctionalInterface
public interface BeanFactoryPostProcessor {

	/**
	 * Modify the application context's internal bean factory after its standard
	 * initialization. All bean definitions will have been loaded, but no beans
	 * will have been instantiated yet. This allows for overriding or adding
	 * properties even to eager-initializing beans.
	 * @param beanFactory the bean factory used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

在标准的实例化过程之后,可以修改容器内部的beanFactory。在这时所有的Bean都被加载,但是没有被初始化。这就允许重写或者添加配置,甚至是提前初始化Bean

使用

public class MyBean implements InitializingBean, DisposableBean {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public void destroy() throws Exception {
        System.out.println("Bean被销毁");
        this.age = null;
        this.name = null;
    }


    public void afterPropertiesSet() throws Exception {
        System.out.println("this.getName() = " + this.getName());
        System.out.println("this.getAge() = " + this.getAge());
        System.out.println("Bean初始化");
        this.age = 10;
        this.name = "josiah";
    }
}
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
        System.out.println("PostProcessFactory");
    }
}

public class MyBeanPostProcessor implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization");
        if (bean.getClass().isAssignableFrom(MyBean.class)) {
           MyBean myBean =  ((MyBean) bean);
           myBean.setAge(20);
           myBean.setName("Bob");
           return myBean;
        }
        return bean;
    }

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

public class Application {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        MyBean myBean = context.getBean("myBean", MyBean.class);
        System.out.println("myBean.getAge() = " + myBean.getAge());
        System.out.println("myBean.getName() = " + myBean.getName());
        context.close();
    }
}

在这里插入图片描述

Spring Bean的生命周期

根据上面的测试结果,可以总结一下Spring 中Bean的生命周期是怎么回事儿

  1. 解析XML文件,解析得到BeanDefinition
  2. Spring 容器创建BeanFactoryPostProcessor实例
  3. 调用BeanFactoryPostProcessor的postProcessBeanFactory方法
  4. Spring容器创建BeanPostProcessor实例
  5. 在需要创建其他Bean的时候,创建其他Bean
  6. 调用Bean的构造方法
  7. 调用Bean的setter方法为Bean属性赋值
  8. 调用BeanPostProcessor的postProcessBeforeInitialization方法
  9. 调用Bean的初始化方法
  10. 调用BeanPostProcessor的postProcessAfterInitialization方法
  11. 调用Bean的destory()方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值