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

相关推荐
Lee川2 小时前
LangChain 加持:后端 AI 流式对话的优雅实现
后端
Javatutouhouduan2 小时前
2026Java面试的正确打开方式!
java·高并发·java面试·java面试题·后端开发·java编程·java八股文
JAVA面经实录9173 小时前
Java初级最终完整版学习路线图
java·spring·eclipse·maven
子兮曰4 小时前
Bun v1.3.14 深度解析:Image API、HTTP/3、全局虚拟存储与五十项变革
前端·后端·bun
Cat_Rocky4 小时前
k8s-持久化存储,粗浅学习
java·学习·kubernetes
ltl4 小时前
Self-Attention:让序列自己看自己
后端
楼兰公子4 小时前
buildroot 在编译rust时裁剪平台类型数量的方法
开发语言·后端·rust
知识领航员4 小时前
蘑兔AI音乐深度实测:功能拆解、实测表现与适用场景
java·c语言·c++·人工智能·python·算法·github
吴声子夜歌4 小时前
Go——并发编程
开发语言·后端·golang
释怀°Believe4 小时前
Spring解析
java·后端·spring