SpringBoot替换容器内注入的Bean

在开发的过程中,经常引入别人写的jar包实现某功能。而别的jar包一般都自动注入Spring容器中,假设都是通过@Bean、@Service或@Component注入的,并且没有加入@ConditionalXXX等注解,导致无法替换掉别人的实现,假设这时就想替换掉,那该如何实现呢?

  1. BeanDefinitionRegistry 是一个接口,它定义了关于 BeanDefinition 的注册、移除、查询等一系列的操作。
  2. BeanDefinitionRegistryPostProcessor接口常用于给接口动态添加代理类。
  • BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor 都是spring的后置处理器,但是两个类的侧重点不一样,
  • BeanDefinitionRegistryPostProcessor 侧重于创建自定义的bd 而 BeanFactoryPostProcessor侧重于对已有bd属性的修改。
  • BeanDefinitionRegistryPostProcessor 先于 BeanFactoryPostProcessor 执行

参考

替换Spring容器中已经存在的Bean
Spring(五)核心容器 - 注册 Bean、BeanDefinitionRegistry 简介
Spring之27:BeanDefinitionRegistry
BeanDefinitionRegistryPostProcessor作用及加载顺序
BeanDefinitionRegistryPostProcessor的作用及和 BeanFactoryPostProcessor 的区别
BeanDefinitionRegistryPostProcessor——动态注册Bean到Spring容器

代码

pom

<properties>
    <java.version>1.8java.version>
    <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
    <spring-boot.version>2.3.1.RELEASEspring-boot.version>
properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>cn.hutoolgroupId>
        <artifactId>hutool-coreartifactId>
        <version>5.3.8version>
    dependency>

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
    dependency>
dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-dependenciesartifactId>
            <version>${spring-boot.version}version>
            <type>pomtype>
            <scope>importscope>
        dependency>
    dependencies>
dependencyManagement>

验证代码-java

接口

/**
 * 替换Spring容器中已经存在的Bean-接口
 *
 * @author z.y.l
 * @version v1.0
 * @date 2022/10/8
 */
public interface DemoMasterService {
    /**
     * 主函数
     */
    void init();
}

源实现类

import xx.xxx.spring.boot.branch.service.DemoMasterService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

/**
 * 替换Spring容器中已经存在的Bean-主
 *
 * @author z.y.l
 * @version v1.0
 * @date 2022/10/8
 */
@Service("demoMasterService")
public class DemoMasterServiceImpl implements DemoMasterService {
    private final Logger logger = LoggerFactory.getLogger(DemoMasterServiceImpl.class);
    @Override
    public void init() {
        logger.info("替换Spring容器中已经存在的Bean-主");
    }
    @PostConstruct
    private void post(){
        logger.info("类初始化-主》》》》》");
    }
}

替代类

import xx.xxx.spring.boot.branch.service.DemoMasterService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;

/**
 * 替换Spring容器中已经存在的Bean-替代类,不使用 @Service
 *
 * @author z.y.l
 * @version v1.0
 * @date 2022/10/8
 */
public class DemoReplaceServiceImpl implements DemoMasterService {
    private final Logger logger = LoggerFactory.getLogger(DemoReplaceServiceImpl.class);
    @Override
    public void init() {
        logger.info("替换Spring容器中已经存在的Bean-替代");
    }
    @PostConstruct
    private void post(){
        logger.info("类初始化-替代》》》》》");
    }
}

实现 spring 的类 BeanDefinitionRegistryPostProcessor,进行容器内类的偷天换日。

import xx.xxx.spring.boot.branch.service.impl.DemoReplaceServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
import org.springframework.stereotype.Component;

/**
 * 替换 管理类
 *
 * @author z.y.l
 * @version v1.0
 * @date 2022/10/8
 */
@Component
public class OverrideExistsBeanDefRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    private final Logger logger = LoggerFactory.getLogger(OverrideExistsBeanDefRegistryPostProcessor.class);
    private final static String NAME = "demoMasterService";
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        String[] names = registry.getBeanDefinitionNames();
        logger.info("替换 管理类>>>>>,总注册类:{}",names.length);
        if(registry.containsBeanDefinition(NAME)){
            String beanName = registry.getBeanDefinition(NAME).getBeanClassName();
            logger.info("替换 管理类,替换目标类-移除源实现类,{}",beanName);
            registry.removeBeanDefinition(NAME);
            GenericBeanDefinition definition = new GenericBeanDefinition();
            logger.info("替换 管理类,替换目标类-注入替代实现类");
            definition.setBeanClass(DemoReplaceServiceImpl.class);
            registry.registerBeanDefinition(NAME,definition);
            beanName = registry.getBeanDefinition(NAME).getBeanClassName();
            logger.info("替换 管理类,替换目标类-最终实现类,{}",beanName);
        }
    }

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

测试

c.z.s.b.b.c.OverrideExistsBeanDefRegistryPostProcessor [OverrideExistsBeanDefRegistryPostProcessor.java:31] =.= 替换 管理类>>>>>,总注册类:131
c.z.s.b.b.c.OverrideExistsBeanDefRegistryPostProcessor [OverrideExistsBeanDefRegistryPostProcessor.java:34] =.= 替换 管理类,替换目标类-移除源实现类,cn.zyl.spring.boot.branch.service.impl.DemoMasterServiceImpl
c.z.s.b.b.c.OverrideExistsBeanDefRegistryPostProcessor [OverrideExistsBeanDefRegistryPostProcessor.java:37] =.= 替换 管理类,替换目标类-注入替代实现类
c.z.s.b.b.c.OverrideExistsBeanDefRegistryPostProcessor [OverrideExistsBeanDefRegistryPostProcessor.java:41] =.= 替换 管理类,替换目标类-最终实现类,cn.zyl.spring.boot.branch.service.impl.DemoReplaceServiceImpl
o.s.b.w.e.t.TomcatWebServer [TomcatWebServer.java:108] =.= Tomcat initialized with port(s): 8080 (http)
...
c.z.s.b.b.s.i.DemoReplaceServiceImpl [DemoReplaceServiceImpl.java:24] =.= 类初始化-替代》》》》》

END

你可能感兴趣的:(demo,Java,springboot,spring,boot,java,spring,替换,demo)