解决Springboot starter先于Dubbo加载,而无法在starter中使用dubbo的provider

起因

最近有一个落地项目,需要对接另一个落地的用户中心。由于落地项目将服务治理组件由集团组件切换为了开源组件dubbo,而且我们的项目未基于用户中心的框架开发,导致我们接入时,需要自行处理相关的问题,其中比较麻烦的一个问题就是今天要说的。
用户中心的实现是基于shiro,我们的项目基于springboot开发,在项目启动时,通过用户中心自定义的@EnableShiro注解导入用户中心相关配置,注解中通过@Import导入实际配置类,实际配置类中又通过方法参数注入的方式注入了dubbo的provider,然后问题就出现在这里了,由于依赖注入使用的是方法参数自动注入,是由Spring完成的,所以会导致获取不到dubbo的provider而导致启动失败,大致代码如下,AuthAgent就是出现问题的依赖

@Bean("shiroFilter")
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager, AuthAgent authAgent) {
  return null;
}

解决

既然知道问题出在哪里了,那就好解决了,但是,我想的好像过于简单。。。
第一次尝试:既然是因为Spring获取不到dubbo的provider,那我就通过@Bean,把实例放到IOC中呗,所以有了如下代码:

@Reference
private AuthAgent authAgent;

@Bean
public AuthAgent getAuthAgent() {
  return authAgent;
}

然鹅,这样做的结果就是,一个null被放入了IOC,错误从没有找到实例变成了空指针异常

第二次尝试:通过@AutoConfigureBefore注解,想着自己写一个新的配置类,在配置类里注入provider,然后让这个配置类先于shiro的配置类加载不就好了么,但是结果却是,这个注解并未生效,shiro还是先于自定义的配置加载了

@Configuration
@EnableShiro
@AutoConfigureBefore(ShiroConfig.class)
public class TestConfig {

    @Reference(version = "1.0.0")
    private AuthAgent authAgent;

    @Bean
    public userArgumentResolver register() {
        return null;
    }
}

第三次尝试:经历了前两次失败后,就想着手动加载dubbo的实现了,但是由于之前并未使用过dubbo,所以开始翻找dubbo的源码,dubbo的服务注入依赖的是@Reference注解,所以我们从这个注解开始



通过IDEA找到使用过该注解的类,发现一个ReferenceAnnotationBeanPostProcessor类,通过名字可以知道,该类实现了BeanPostProcessor接口,而且spring也是通过该接口来实现的@Autowired和@Value,所以我们就进入这个实现类



通过文档,我们就更加确定我们找对地方了,接下来,我们再一步步看具体的实现

这个方法为主要的执行方法,我们看下该方法是如何处理的
该方法一共执行了五个步骤,分别是:
第一步,构建引用的名字
第二步,创建引用对象
第三步,注册实例
第四步,添加缓存
第五步,返回代理对象注入
第一步的实例名称主要用于后面的依赖注册和缓存使用,这里就直接跳过名字的构建方法了,



第二步的实例构建,会先去缓存中查找是否有对应的实例,如果没有的话,通过ReferenceBeanBuilder创建一个新的实例,并添加到缓存中,ReferenceBeanBuilder的create方法仅仅是new了一个ReferenceBeanBuilder对象,interfaceClass方法则是为ReferenceBeanBuilder设置属性,这里我们都不多说了,代码比较简单,自己查看即可。

build方法是ReferenceBeanBuilder的父类AnnotatedInterfaceConfigBeanBuilder提供的方法,checkDependencies为空实现,这里跳过,doBuild是一个抽象方法,由ReferenceBeanBuilder重写,就是new一个ReferenceBean对象

通过doBuild方法创建ReferenceBean对象后,通过configureBean来对ReferenceBean对象进行配置

preConfigureBean方法也是一个抽象方法,被ReferenceBeanBuilder重写,该方法主要是从Environment中获取与Reference注解中定义的属性相同的配置到ReferenceBean的属性中

configureRegistryConfigs,configureMonitorConfig,configureApplicationConfig,configureModuleConfig四个方法的实现基本相同,都是获取对应的配置对象,添加到ReferenceBean的属性中,

postConfigureBean方法主要为ReferenceBean添加接口类,consumer配置,并且调用ReferenceBean的afterPropertiesSet来初始化实例

到这里,整个ReferenceBean就算初始化完了,总结一下,大致的流程就是,先new一个ReferenceBean,给实例添加属性,调用afterPropertiesSet完成初始化。

第三步,注册ReferenceBean实例到IOC容器,这里会先查找一下是否已有实例,如果有的话,则只添加一个别名,如果没有的话,则注册一个单例到BeanFactory中

第四步:缓存对象,这里会先判断一下,注入的是属性还是方法,再
分开做缓存

第五步,返回一个代理类,这里为什么会返回一个代理类,而非直接返回ReferenceBean则不太清楚了,这里也先不再深究,先已解决问题为主

到这里,dubbo注入provider的原理就清楚了,我们只需要在shiro初始化前手动构建一个我们需要的bean放到beanFactory就好了

  1. 先new一个ReferenceBean<AuthAgent>
  2. 给对象添加属性,由于我这儿所有的配置都在registry,consumer,application下,所以我们添加这几个属性就好
  3. 注册创建的Bean,我这里是通过@Import加ImportBeanDefinitionRegistrar接口实现的

    主要实现代码如下
    使用如下

    这里有一点小插曲,关于配置的获取,我先debug了一下,发现在注册的时候,beanFactory中并没有dubbo的配置对象,所以采用Binder直接从配置文件中绑定配置到对象中再来使用

最终使用该方法完成用户中心的接入

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容