重寫spring bean的幾種方式

概述

工作中會經常會需要重寫jar包中的一個類,開源的jar包或者是其他項目提供的share包,比較通用的做法是下載源碼下來,修改後重新打包。但是很多時候我們只是重寫一個類,下載源碼打包太過繁瑣,而且有可能別人的share沒有提供源碼下載。

可以通過下面幾種方式重寫:
1、直接同包路徑,同報名,進行替換

這種方式簡單粗暴,前提必須是同包路徑,同類名。可以直接覆蓋掉jar包中的類,spring項目會優先加載自定義的類。
比如重寫:DefaultResourceFactory類
在這裏插入圖片描述

2)繼承要替換的類,在配置類中進行配置,返回其子類

1)首先創建一個新的bean,繼承需要被重寫的bean

public class MyHealthMessageQueueLogService extends HealthMessageQueueLogService{
    //需要被重寫的方法
}

2)在啓動類中排除父類

@ComponentScan(excludeFilters = {@Filter(type = FilterType.ASSIGNABLE_TYPE, value = HealthMessageQueueLogService.class)})

3)在配置類中創建子類

@Configuration
public class MessageQueueLogConfig {
    @Bean
    public HealthMessageQueueLogService healthMessageQueueLogService(){
        return new MyHealthMessageQueueLogService();
    }
}
3)使用BeanDefinitionRegistryPostProcessor
/**
 * Created by zhangshukang on 2019/9/16.
 */
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    private static String SPECIAL_OVERRIDE_BEAN = "healthMessageQueueLogService";


    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {


        boolean isContainsSpecialBean = ((DefaultListableBeanFactory) registry).containsBean(SPECIAL_OVERRIDE_BEAN);

        if (isContainsSpecialBean) {
            AnnotatedBeanDefinition healthMessageBeanDefinition = (AnnotatedBeanDefinition) registry.getBeanDefinition(SPECIAL_OVERRIDE_BEAN);
            if (healthMessageBeanDefinition != null) {
                AnnotatedGenericBeanDefinition myBeanDefinition = new AnnotatedGenericBeanDefinition(healthMessageBeanDefinition.getMetadata());
                //忽略beanClass originatingBeanDefinition字段
                BeanUtils.copyProperties(healthMessageBeanDefinition, myBeanDefinition,"beanClass","originatingBeanDefinition");
                //設置自定義的bean class
                myBeanDefinition.setBeanClass(MyHealthMessageQueueLogService.class);
                //重新加載自定義的bean class
                try {
                    myBeanDefinition.resolveBeanClass(Thread.currentThread().getContextClassLoader());
                    registry.registerBeanDefinition(SPECIAL_OVERRIDE_BEAN,myBeanDefinition);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章