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 的替换操作。

相关推荐
小江的记录本13 分钟前
【Spring Boot—— .yml(YAML)】Spring Boot中.yml文件的基础语法、高级特性、实践技巧
xml·java·spring boot·后端·spring·spring cloud·架构
I_LPL16 分钟前
day52 代码随想录算法训练营 图论专题6
java·数据结构·算法·图论
爱敲代码的小黄24 分钟前
Agent 能力模块化:Skill 设计与执行机制解析
人工智能·后端·面试
2601_9534656127 分钟前
m3u8live.cn深度解析:一款专为开发者打造的 M3U8 调试工具
java·前端·django·音视频·开发工具
掘金者阿豪31 分钟前
告别SQL性能焦虑:金仓数据库“连接条件下推”的性能魔法
后端
稻草猫.36 分钟前
SpringBoot日志全解析:从调试到持久化
java·开发语言·spring boot·java-ee·idea
zopple37 分钟前
Knife4j文档请求异常(基于SpringBoot3,查找原因并解决)
java·服务器·数据库
老友@44 分钟前
接口调用的演进史——从“发 HTTP 请求”到“可治理的系统能力
spring boot·后端·架构
清水白石0081 小时前
Python 弱引用深度解析——让缓存不再成为内存泄漏的温床
java·python·缓存
zzb15801 小时前
RAG from Scratch-优化-routing
java·前端·网络·人工智能·后端·python·mybatis