spring 优雅替换bean

方案一:使用 @Primary/@Qualifier 注解(优选)

如果有多个相同类型的 Bean 存在,可以将想要优先使用的 Bean 加上 @Primary 注解。

@Qualifier和@Primary注解的区别:@Primary注解用于标记具有相同类型的多个实例中的主要实例。而@Qualifier注解用于标记具有特定名称的Bean,以便在多个具有相同类型的Bean中选择特定的实例。

例如:接口ContextUserParser有AbsContextUserTokenParser和ContextUserTokenParser两个实现类,现在我想使用AbsContextUserTokenParser。为此配置config类:

java 复制代码
package com.psbc.abs.config;

import com.psbc.pfpj.yoaf.context.autoconfigure.YoafUserContextProperties;
import com.psbc.pfpj.yoaf.context.parser.AbsContextUserTokenParser;
import com.psbc.pfpj.yoaf.context.parser.ContextUserParser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration
@Slf4j
public class AbsContextUserTokenConfig {
    @Bean
    @Primary
    public ContextUserParser absContextUserTokenParser(YoafUserContextProperties properties){
        return new AbsContextUserTokenParser(properties);
    }
}

方式二:自定义 Bean 替换逻辑

通过实现BeanDefinitionRegistryPostProcessor 接口,在其方法中根据特定条件来动态替换 Bean 的定义。

以下是一个简单示例:

java 复制代码
package com.psbc.abs.support;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;

/**
 * 替换jar包内默认bean
 *
 * @author lijunyu
 * @date 2023/10/23 17:55
 */
@Slf4j
public class OverrideExistsBeanProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        replaceClass(registry,"contextUserParser", AbsContextUserTokenParser.class);
    }

    /**
     * 对容器内现有类进行替换
     *
     * @param beanName 替换类名
     * @param clazz    替换类
     */
    public void replaceClass(BeanDefinitionRegistry registry,String beanName, Class clazz) {
        if (registry.containsBeanDefinition(beanName)) {
            log.debug("bean:{} 删除", beanName);
            registry.removeBeanDefinition(beanName);
            GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
            beanDefinition.setBeanClass(clazz);
            registry.registerBeanDefinition(beanName, beanDefinition);
            log.debug("bean:{} 替换成功", beanName);
        }
    }


    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        log.debug("beanFactory:{}", beanFactory);
        
    }
}

方式三:利用 Spring 的扩展机制

比如通过自定义 ApplicationContextInitializer 等在特定阶段进行 Bean 的替换操作。

相关推荐
张同学的IT技术日记9 分钟前
必看!用示例代码学 C++ 基础入门,快速掌握基础知识,高效提升编程能力
后端
UserNamezhangxi18 分钟前
kotlin 协程笔记
java·笔记·kotlin·协程
林太白18 分钟前
Nuxt3 功能篇
前端·javascript·后端
咖啡里的茶i27 分钟前
数字化图书管理系统设计实践(java)
java·课程设计
杨杨杨大侠28 分钟前
Spring AI Alibaba Multi-Agent 架构详解
spring·aigc
得物技术42 分钟前
营销会场预览直通车实践|得物技术
后端·架构·测试
九转苍翎1 小时前
Java内功修炼(2)——线程安全三剑客:synchronized、volatile与wait/notify
java·thread
曲莫终1 小时前
正则表达式删除注释和多余换航
java·kotlin
Ice__Cai1 小时前
Flask 入门详解:从零开始构建 Web 应用
后端·python·flask·数据类型
武子康1 小时前
大数据-74 Kafka 核心机制揭秘:副本同步、控制器选举与可靠性保障
大数据·后端·kafka