Spring的BeanFactoryPostProcessor
- spring
- 时间:2022-11-10 16:06
- 4668人已阅读
🔔🔔🔔好消息!好消息!🔔🔔🔔
有需要的朋友👉:联系凯哥
BeanFactoryPostProcessor是实现spring容器功能扩展的重要接口,例如修改bean属性值,实现bean动态代理等。很多框架都是通过此接口实现对spring容器的扩展,例如mybatis与spring集成时,只定义了mapper接口,无实现类,但spring却可以完成自动注入,是不是很神奇? 本文将通过简单的例子,展现BeanFactoryPostProcessor的扩展能力。
一、bean生命周期简述
Spring Bean生命周期比较复杂,在此简化一下,如下图。
步骤1、 豆子工厂(BeanFactory)从xml文件、java配置或注解配置中读取“各种豆子的生产方法说明(BeanDefinition)”。
步骤2、 这些豆子分为“特殊豆子(实现spring指定的某些接口)”和“普通豆子”, 豆子工厂先生产出这些特殊豆子。
步骤3和4、 特殊豆子调用特定接口(例如BeanFactoryPostProcessor接口),可以对豆子工厂(BeanFactory)进行修改,或添加一些新豆子生产方法(即注册新的BeanDefinition到BeanFactory中)。
步骤5、豆子工厂(BeanFactory)执行getBean方法生产其他的普通裸豆子。(调用类的构造方法,或FactoryBean的getObject方法,以及@Bean注解的方法)
步骤6、设置豆子的依赖关系以及属性值。
步骤7、调用豆子的@PostConstruct指定的方法
步骤8、调用豆子的InitializingBean接口方法
步骤9、调用豆子的initMethod指定的方法。
总结上述过程, 我们可以得到以下执行顺序 : BeanFactoryPostProcessor ---> 普通Bean构造方法 ---> 设置依赖或属性 ---> @PostConstruct ---> InitializingBean ---> initMethod 。
二、BeanFactoryPostProcessor 代码例子
BenzCar类(奔驰汽车类)有成员属性Engine(发动机), Engine是接口,无具体的实现类。本代码例子,通过BeanFactoryPostProcessor ,FactoryBean,动态代理三项技术实现给BenzCar装配上Engine。
项目结构如下:
AppConfig类如下:
com.kaigejava.spring.beanlife.configcom.kaigejava.spring.beanlife.bean.BenzCarcom.kaigejava.spring.beanlife.bean.specialbean.SpecialBeanForEnginecom.kaigejava.spring.beanlife.service.Engineorg.springframework.context.annotation.org.springframework.context.annotation.AppConfig { SpecialBeanForEngine (){ SpecialBeanForEngine()} (initMethod=) BenzCar (Engine engine){ BenzCar car = BenzCar()car.= enginecar } }
从@Bean benzCar,我们可以看出,car需要一个engine对象。
以下是BenzCar 代码:
package com.kaigejava.spring.beanlife.bean; import com.kaigejava.spring.beanlife.service.Engine; import org.springframework.beans.factory.InitializingBean; import javax.annotation.PostConstruct; /** * @author 凯哥Java * @description * @company * @since 2022/11/10 15:03 */ public class BenzCar implements InitializingBean { public Engine engine; public BenzCar(){ System.out.println(" BenzCar 无参构造器...."); if(engine == null){ System.out.println(" engine not setting ~~~~"); }else{ System.out.println(" engine 已经初始化"); } } void startCar(){ System.out.println(" BeanzCar start ===="); engine.fire(); } @Override public void afterPropertiesSet() throws Exception { System.out.println("BenzCar afterPropertiesSet method ... "); if(engine == null){ System.out.println(" afterPropertiesSet engine not setting ~~~~"); }else{ System.out.println(" afterPropertiesSet engine 已经初始化"); engine.fire(); } } @PostConstruct public void postConstruct(){ System.out.println(" BenzCar postConstruct...."); if(engine == null){ System.out.println(" postConstruct => engine not setting ~~~~"); }else{ System.out.println(" postConstruct => engine 已经初始化"); } } }
BenzCar 实现类 InitializingBean 类,重写了afterPorpertiesSet方法。有一个Engine对象成员, 在start方法中调用Engine的fire方法。
Engine接口代码如下:
com.kaigejava.spring.beanlife.serviceEngine { ()}
Engine是一个接口,一般情况下,需要在App类中配置一个Engine的实现类bean才行,否则因为缺少Engine实例,spring启动时会报错。通过FactoryBean和动态代理,可以生成Engine接口的代理对象;结合BeanFactoryPostProcessor 接口,将FactoryBean动态添加到BeanFactory中,即可以给BenzCar配置上Engine接口代理对象。
为此新增一个 SpecialBeanForEngine类, 代码如下:
com.kaigejava.spring.beanlife.bean.specialbeancom.kaigejava.spring.beanlife.factory.EngineFactoryorg.springframework.beans.BeansExceptionorg.springframework.beans.factory.BeanNameAwareorg.springframework.beans.factory.config.BeanDefinitionorg.springframework.beans.factory.config.BeanFactoryPostProcessororg.springframework.beans.factory.config.ConfigurableListableBeanFactoryorg.springframework.beans.factory.support.BeanDefinitionRegistryorg.springframework.beans.factory.support.GenericBeanDefinitionSpecialBeanForEngine BeanFactoryPostProcessorBeanNameAware { String (String name) { .= name} (ConfigurableListableBeanFactory configurableListableBeanFactory) BeansException { BeanDefinitionRegistry bdr = (BeanDefinitionRegistry) configurableListableBeanFactoryGenericBeanDefinition gbd = GenericBeanDefinition()gbd.setBeanClass(EngineFactory.)gbd.setScope(BeanDefinition.)gbd.setAutowireCandidate()bdr.registerBeanDefinition(gbd)} }
在postProcessBeanFactory方法中添加了 EngineFactory.class类的Bean。 EngineFactory 是一个FactoryBean,代码21-24行在getObject()方法中,使用动态代理生产Engine接口的代理对象。
启动类:
com.kaigejava.spring.beanlifecom.kaigejava.spring.beanlife.config.AppConfigorg.springframework.context.annotation.AnnotationConfigApplicationContextMainApplication { (String[] args) { AnnotationConfigApplicationContext context = AnnotationConfigApplicationContext()context.register(AppConfig.)context.refresh()} }
执行后结果:
源码:https://gitee.com/kaigejava/kaigejavastudy