spring bean 擴充套件方式

CyrusHuang發表於2024-06-29

BeanFactoryPostProcessor

觸發時機是:**所有的 beanDefinition 收集完成,將要進行物件例項化的階段,這時可以修改 beanDefinition 或 新增 beanDefinition **

BeanFactoryPostProcessor 是個函式式介面,介面定義如下:

@FunctionalInterface
public interface BeanFactoryPostProcessor {
    // ConfigurableListableBeanFactory 是 beanFactory 的子介面,所以可以拿到 beanDefinition
    // 處於安全,不會讓你拿到所有 beanDefinition,只能透過特定條件拿指定的 beanDefinition,比如透過名稱
    void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;
}

用法示例:修改 bean 的型別,原本是 UserDao,修改後成為 OrderDao

@Component
public class Test implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        // 假設配置了個bean,class 是 com.study.user.userDao,id 是 userDao
        BeanDefinition userDao = configurableListableBeanFactory.getBeanDefinition("userDao");
        // 把這個配置的 class 改為 com.study.order.orderDao
        userDao.setBeanClassName("com.study.order.orderDao");
        // 這時 ApplicationContext 獲取 userDao 實際就是 orderDao 了
    }
}

用法示例:新增 beanDefinition

@Component
public class Test implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        // RootBeanDefinition 是 beanDefinition 子介面
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClassName("com.study.person.personDao");

        // configurableListableBeanFactory 沒有註冊 beanDefinition 的方法,但是它的父類有
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;

        // beanDefinition 新增到 beanDefinitionMap 中
        defaultListableBeanFactory.registerBeanDefinition("personDao", beanDefinition);
    }
}

BeanDefinitionRegistryPostProcessor

是 BeanFactoryPostProcessor 的子介面,如果只是想單純增加 beanDefinition,這個更方便

介面定義:

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}

用法示例:

@Component
public class TestExtBeanDefinition implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // 建立一個新的 BeanDefinition
        BeanDefinition customBeanDefinition = BeanDefinitionBuilder
            	.rootBeanDefinition(CustomBean.class)
                .getBeanDefinition();

        // 將新的 BeanDefinition 註冊到 Spring 容器中
        registry.registerBeanDefinition("customBean", customBeanDefinition);
    }

}

BeanPostProcessor

觸發時機是:bean 的物件已經例項化,正在完善配置的階段

介面定義如下:

public interface BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

用法示例:修改 User 型別 的 bean 屬性 username

@Component
public class Test implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 如果 bean 是 User 才修改,不然所有的 bean 都要被修改
        if (bean instanceof User){
            System.out.println("BeanPostProcessor.before");
            User userBean = (User) bean;
            userBean.username = "張三";
            // 返回修改後的 bean
            return userBean;
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 同 postProcessBeforeInitialization 一樣,只不過這是最後步驟,一般也是 after 擴充套件居多
    }

}

相關文章