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
看看到底是哪⼀个Bean (); }}控制台打印如下:可以发现,和我们期望的结果的⼀样:所有⽤到 MyTestService的地⽅实际调⽤的变成了MyTestServiceIpml⾥⾯的⽅法 !OVER …
发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1690215716a316073.html
评论列表(0条)