在Springboot中重建RestTemplate Bean
最近有个需求,用户希望RestTemplate能够绕过ssl证书验证,直接访问目标地址。虽然这并不安全,但是作为开发人员,只能有求必应啊。
需要设计一个开关,是否忽略ssl验证,默认为false。而且配置得动态刷新,也就是说,一旦修改了配置,就要重新生成一个RestTemplate。
实现思路如下:
- 增加一个配置
rest-template.ignore-ssl-validation,初始值为false。 - 修改
RestTemplate初始化逻辑,根据配置来决定生成的RestTemplate的方式。 - 写一个
RestTempalteRebuilder类,包含重新生成RestTemplate的逻辑,新建一个RestTemplate bean,从spring中销毁旧的bean,再向spring中注册新的bean。 - 实现一个
ApplicationListener,监听RefreshEvent事件,如果该配置发生变化,则调用RestTempalteRebuilder的重建RestTemplate方法。
遇到的问题:
ApplicationListener初始化完成后,注解了@ConfigurationProperties的类还没有初始化完,获取的值为null!!!ApplicationListener的执行顺序在RefreshEventListener之前,当监听器触发时,获取不到变化后的值,慢了整整一个八拍!!!
解决办法:
- 实现
InitialingBean和afterPropertiesSet()方法,意思时在依赖的bean全部初始化好之后执行这个方法,所以可以在这里方法里去初始化读取到的配置的值。 - 注入
ContextRefresher,当自定义的监听器执行的时候,就去刷新以下缓存,就可以取到变化后的值了。
替换context中的bean
DefaultSingletonBeanRegistry registry = (DefaultSingletonBeanRegistry) applicationContext.getAutowireCapableBeanFactory();
registry.destroySingleton("restTemplate");
registry.registerSingleton("restTemplate", new RestTemplate()); 首先从ApplicationContext中获取到DefaultSingletonBeanRegistry,使用destroySingleton()来销毁restTemplate bean, 然后使用registerSingleton()将新建好的bean再注册进去,这个registerSingleton() 方法不仅会在 ApplicationContext 中创建 bean,还会自动将其注入到依赖的对象中,完美。
评论区