SpringBoot替换容器内注入的Bean
> 在开发的过程中,经常引入别人写的jar包实现某功能。而别的jar包一般都自动注入Spring容器中,假设都是通过@Bean、@Service或@Component注入的,并且没有加入@ConditionalXXX等注解,导致无法替换掉别人的实现,假设这时就想替换掉,那该如何实现呢?> 1. BeanDefinitionRegistry 是一个接口,它定义了关于 BeanDefinition 的
·
在开发的过程中,经常引入别人写的jar包实现某功能。而别的jar包一般都自动注入Spring容器中,假设都是通过@Bean、@Service或@Component注入的,并且没有加入@ConditionalXXX等注解,导致无法替换掉别人的实现,假设这时就想替换掉,那该如何实现呢?
- BeanDefinitionRegistry 是一个接口,它定义了关于 BeanDefinition 的注册、移除、查询等一系列的操作。
- 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
*/
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
更多推荐
已为社区贡献1条内容
所有评论(0)