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

相关推荐
一技安身1 分钟前
【java】JDK8 + JDK17 绿色解压共存方案-全程不修改任何系统环境变量
java·开发语言
松就是我9029834 分钟前
如何搭建一个 Agent 系统:方法论、理想形态与一次真实落地
后端
Layer36 分钟前
即时通讯系统的关键设计
后端·架构
java、iOS、Vue37 分钟前
Maven antrun vs Jenkins 脚本组装 deb的优缺点、适用场景
java·jenkins·maven
hudd6681 小时前
JavaEE 初阶 - 多线程(初阶)
java·开发语言·java-ee
CarIise1 小时前
Java实训阶段查漏补缺复习笔记2
java·linux·算法
Wang's Blog1 小时前
Java框架 SpringCloud 快速入门: Feign 的性能优化
java·spring cloud·性能优化
golang学习记1 小时前
rust开发,选VS Code还是RustRover?
开发语言·后端·rust
蛋蛋的就会顺顺的1 小时前
hot100——二叉树
java·数据结构·算法·leetcode·力扣
打工仔折腾 AI2 小时前
System Prompt 替代 Few-shot:用规则约束大模型输出的省钱实践
java·人工智能·python·spring·langchain·prompt·ai agent 实战