覆盖重写原有SpringBean的几种方式

覆盖重写原有SpringBean的几种方式

2023年7月25日发(作者:)

覆盖重写原有SpringBean的⼏种⽅式⽬录场景什么情况下要覆写原有的Spring Bean ? 例如引⼊的第三⽅jar包中的某个类有些问题,然有没有源码提供或者嫌编译源码太费事,这个时间可以考虑覆写原有的类。⽅法1 直接在⾃⼰⼯程中建同包同类名的类进⾏替换⽅式简单粗暴,可以直接覆盖掉jar包中的类,spring项⽬会优先加载⾃定义的类。下⾯是覆盖 flowable框架中的⼀个类 FlowableCookieFilter,主要是想修改它⾥⾯的redirectToLogin⽅法的业务逻辑。包路径为, 直接⼯程⾥⾯新建⼀样路径⼀样类名FlowableCookieFilter即可。⽅法2 采⽤@Primary注解该⽅法适⽤于接⼝实现类,⾃⼰创建⼀个原jar包接⼝的实现类,然后类上加上@Primary注解,spring则默认加载该类实例化出的Bean。下⾯的例⼦: ⼀个接⼝ RemoteIdmService,原先jar包中只有⼀个实现类 RemoteIdmServiceImpl,现在⾃⼰⼯程⾥⾯创建⼀个CustomRemoteIdmServiceImpl 继承RemoteIdmService接⼝,然后发现所有调⽤RemoteIdmService接⼝⾥⾯的⽅法实际调⽤⾛的是CustomRemoteIdmServiceImpl ⾥⾯的⽅法。⽅法3 排除需要替换的jar包中的类使⽤ @ComponentScan ⾥⾯的 excludeFilters 功能排除调⽤要替换的类,然后⾃⼰写个类继承替换的类即可。下⾯的例⼦是替换掉 jar包中的PersistentTokenServiceImpl类@SpringBootApplication@ComponentScan(excludeFilters = {@(type =

ABLE_TYPE, classes = {})})public class Application { public static void main(String[] args) { new SpringApplication().run(args); }}@Servicepublic class MyPersistentTokenServiceImpl extends PersistentTokenServiceImpl{ @Override public Token saveAndFlush(Token token) { //

覆写该⽅法的业务逻辑 ((), token); ken(token); return token; } @Override public void delete(Token token) { //

覆写该⽅法的业务逻辑 date(()); Token(()); } @Override public Token getPersistentToken(String tokenId) { //

覆写该⽅法的业务逻辑 return getPersistentToken(tokenId, false); }}⽅法4 @Bean 覆盖该场景针对,框架jar包中有@ConditionalOnMissingBean注解,这种注解是说明如果你也创建了⼀个⼀样的Bean则框架就不⾃⼰再次创建这个bean了,这样你可以覆写⾃⼰的bean。原jar包中的配置类:直接继承要覆盖的类,⾃⼰重写⾥⾯⽅法,使⽤@Component注⼊到spring中去⽅法5 使⽤BeanDefinitionRegistryPostProcessorBeanDefinitionRegistryPostProcessor 说⽩了就是可以在初始化Bean之前修改Bean的属性,甚⾄替换原先准备要实例化的bean。实战演⽰:假设jar包中有⼀个类 MyTestService,正常情况下它会被spring⾃动扫描到注⼊IOC容器中去。package ;import e;import nstruct;import troy;/** * @author guzt */@Service("myTestService")public class MyTestService { private String name1; private String name2; private String name3; public MyTestService() { 1 = ""; 2 = ""; 3 = ""; } public MyTestService(String name1, String name2, String name3) { 1 = name1; 2 = name2; 3 = name3; } @PostConstruct public void init() { n("MyTestService init"); } @PreDestroy public void destory() { n("MyTestService destroy"); } public void show() { n("------------------------"); n("我是jar中通过注解@Service主动加⼊Spring的IOC⾥⾯的"); n("------------------------"); } public String getName1() { return name1; } public void setName1(String name1) { 1 = name1; } public String getName2() { return name2; } public void setName2(String name2) { 2 = name2; } public String getName3() { return name3; } public void setName3(String name3) { 3 = name3; }}⾃⼰⼯程中继承该类,并且覆写⾥⾯的show中的⽅法package er;import Service;/** * @author guzt */public class MyTestServiceIpml extends MyTestService { public MyTestServiceIpml() { } public MyTestServiceIpml(String name1, String name2, String name3) { super(name1, name2, name3); } @Override public void show() { n("------------------------"); n("我是被BeanDefinitionRegistry⼿动注册到Spring的IOC⾥⾯的"); n("------------------------"); }}然后 实现 BeanDefinitionRegistryPostProcessor 接⼝,修改原来bean定义,主要查看postProcessBeanDefinitionRegistry⽅法的实现,先清空原bean定义,注册我们⾃⼰的bean定义来达到替换的⽬的。package er;import ;import Factory;import xception;import urableListableBeanFactory;import finitionBuilder;import finitionRegistry;import finitionRegistryPostProcessor;import ent;import ntroller;import ;/** * @author amdin */@Componentpublic class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { private Logger logger = ger(ss()); @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException { ("bean 定义查看和修改..."); String beanName = "myTestService"; //

先移除原来的bean定义 BeanDefinition(beanName); //

注册我们⾃⼰的bean定义 BeanDefinitionBuilder beanDefinitionBuilder = anDefinition(); //

如果有构造函数参数,

有⼏个构造函数的参数就设置⼏个

没有就不⽤设置 structorArgValue("构造参数1"); structorArgValue("构造参数2"); structorArgValue("构造参数3"); //

设置 init⽅法

没有就不⽤设置 tMethodName("init"); //

设置 destory⽅法

没有就不⽤设置 troyMethodName("destory"); //

将Bean

的定义注册到Spring环境 erBeanDefinition("myTestService", nDefinition()); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { // bean的名字为key, bean的实例为value Map beanMap = nsWithAnnotation(); ("所有 RestController 的bean {}", beanMap); }}写⼀个 业务类BusinessTestService测试⼀下,期望结果:所有⽤到 MyTestService的地⽅实际调⽤的变成了MyTestServiceIpml⾥⾯的⽅法。package er;import Service;import e;import nstruct;import ce;/** * @author guzt */@Servicepublic class BusinessTestService { @Resource private MyTestService myTestService; @PostConstruct public void init() { n(e1()); n(e2()); n(e3()); //

看看到底是哪⼀个Bean (); }}控制台打印如下:可以发现,和我们期望的结果的⼀样:所有⽤到 MyTestService的地⽅实际调⽤的变成了MyTestServiceIpml⾥⾯的⽅法 !OVER …

发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1690215716a316073.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信