0


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.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.3.1.RELEASE</spring-boot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-core</artifactId><version>5.3.8</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>

验证代码-java

接口

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

源实现类

importxx.xxx.spring.boot.branch.service.DemoMasterService;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.stereotype.Service;importjavax.annotation.PostConstruct;/**
 * 替换Spring容器中已经存在的Bean-主
 *
 * @author z.y.l
 * @version v1.0
 * @date 2022/10/8
 */@Service("demoMasterService")publicclassDemoMasterServiceImplimplementsDemoMasterService{privatefinalLogger logger =LoggerFactory.getLogger(DemoMasterServiceImpl.class);@Overridepublicvoidinit(){
        logger.info("替换Spring容器中已经存在的Bean-主");}@PostConstructprivatevoidpost(){
        logger.info("类初始化-主》》》》》");}}

替代类

importxx.xxx.spring.boot.branch.service.DemoMasterService;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importjavax.annotation.PostConstruct;/**
 * 替换Spring容器中已经存在的Bean-替代类,不使用 @Service
 *
 * @author z.y.l
 * @version v1.0
 * @date 2022/10/8
 */publicclassDemoReplaceServiceImplimplementsDemoMasterService{privatefinalLogger logger =LoggerFactory.getLogger(DemoReplaceServiceImpl.class);@Overridepublicvoidinit(){
        logger.info("替换Spring容器中已经存在的Bean-替代");}@PostConstructprivatevoidpost(){
        logger.info("类初始化-替代》》》》》");}}

实现 spring 的类

BeanDefinitionRegistryPostProcessor

,进行容器内类的偷天换日。

importxx.xxx.spring.boot.branch.service.impl.DemoReplaceServiceImpl;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.beans.BeansException;importorg.springframework.beans.factory.config.ConfigurableListableBeanFactory;importorg.springframework.beans.factory.support.BeanDefinitionRegistry;importorg.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;importorg.springframework.beans.factory.support.GenericBeanDefinition;importorg.springframework.stereotype.Component;/**
 * 替换 管理类
 *
 * @author z.y.l
 * @version v1.0
 * @date 2022/10/8
 */@ComponentpublicclassOverrideExistsBeanDefRegistryPostProcessorimplementsBeanDefinitionRegistryPostProcessor{privatefinalLogger logger =LoggerFactory.getLogger(OverrideExistsBeanDefRegistryPostProcessor.class);privatefinalstaticString NAME ="demoMasterService";@OverridepublicvoidpostProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)throwsBeansException{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 =newGenericBeanDefinition();
            logger.info("替换 管理类,替换目标类-注入替代实现类");
            definition.setBeanClass(DemoReplaceServiceImpl.class);
            registry.registerBeanDefinition(NAME,definition);
            beanName = registry.getBeanDefinition(NAME).getBeanClassName();
            logger.info("替换 管理类,替换目标类-最终实现类,{}",beanName);}}@OverridepublicvoidpostProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)throwsBeansException{}}

测试

在这里插入图片描述

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

标签: spring boot java spring

本文转载自: https://blog.csdn.net/privateobject/article/details/127210353
版权归原作者 privateobject 所有, 如有侵权,请联系我们删除。

“SpringBoot替换容器内注入的Bean”的评论:

还没有评论