Spring的BeanFactoryPostProcessor

  • 作者: 凯哥Java(公众号:凯哥Java)
  • spring
  • 时间:2022-11-10 16:06
  • 3331人已阅读
简介 BeanFactoryPostProcessor是实现spring容器功能扩展的重要接口,例如修改bean属性值,实现bean动态代理等。很多框架都是通过此接口实现对spring容器的扩展,例如mybatis与spring集成时,只定义了mapper接口,无实现类,但spring却可以完成自动注入,是不是很神奇?本文将通过简单的例子,展现BeanFactoryPostProcessor的扩展能力。

🔔🔔好消息!好消息!🔔🔔

 如果您需要注册ChatGPT,想要升级ChatGPT4。凯哥可以代注册ChatGPT账号代升级ChatGPT4

有需要的朋友👉:微信号 kaigejava2022

BeanFactoryPostProcessor是实现spring容器功能扩展的重要接口,例如修改bean属性值,实现bean动态代理等。很多框架都是通过此接口实现对spring容器的扩展,例如mybatis与spring集成时,只定义了mapper接口,无实现类,但spring却可以完成自动注入,是不是很神奇? 本文将通过简单的例子,展现BeanFactoryPostProcessor的扩展能力。

 一、bean生命周期简述

Spring Bean生命周期比较复杂,在此简化一下,如下图。

bac2a136d0083ea4d1c73fbfd32e13fd.png

步骤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。

项目结构如下:

012624488a2721e5f6998c317c757e8c.png

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()}
}

执行后结果:

0f2123cfe007a85e84aecb20343ecb49.png

源码:https://gitee.com/kaigejava/kaigejavastudy


TopTop