为了账号安全,请及时绑定邮箱和手机立即绑定

聊聊springboot自动装配出现的TypeNotPresentExceptionProxy异常排查

标签:
SpringBoot

前言

正文开始前,我们做个小测试,假设我们封装了一个springboot starter,其自动装配类形如下内容

@Configuration
@EnableConfigurationProperties({ApolloRefreshProperties.class})
public class ApolloRefreshAutoConfiguration  {

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnClass({ConfigService.class})
    public ApolloRefreshService apolloRefreshService(ApolloRefreshProperties properties) {
        return new ApolloRefreshService(properties);
    }
    }

该starter的pom引入的apollo gav是optional

  <dependency>
            <groupId>com.ctrip.framework.apollo</groupId>
            <artifactId>apollo-client</artifactId>
            <version>${apollo-client.version}</version>
            <optional>true</optional>
        </dependency>

我的问题是

在运行环境为jdk8的springboot项目引入上述的starter,是否会有问题?

我们运行一下,发现会出现

8cdb7ea2a905b46725895f07d9c33ad0_a9eb03114df579374c86a2791a0aaf07.png

然后我们不改任何一行代码,把JDK调成11或者以上版本,再运行

1a7c9d3d7131e75bd5814fa15a160aac_b1c04c59a161bfdbb81d7f822346b8e7.png

项目成功运行。那我们的修复的第一直觉是不是把JDK8的版本提高。

我们团队的小伙伴第一时间也是这么干的,他去和业务团队的技术经理沟通,看他们能不能把JDK8调整成JDK11,然后得到了业务团队技术经理的高度否定,因为他们大部分业务都跑在jdk8,冒然升级成jdk11,也不知道会不会因为了解决一个问题,而引入其他问题

问题排查

因为这个starter的自动装配配置的内容相对简单,基于老司机的第六感,问题大概率是出现在@ConditionalOnClass这注解上,于是点开@ConditionalOnClass,他的注解上有如下提示

37bbf9d08bd41ee27725df5c9289fca8_47a1f7d7ee4c4734c4cef41d92c31301.png

他的大意是,可以在@Configuration classes上安全地指定value(),因为在加载类之前会使用ASM解析注释元数据。当放置在@Bean方法上时,需要格外小心,请考虑在单独的Configuration类中隔离条件,特别是当方法的返回类型与条件的目标匹配时。如果非要用方法注解,建议使用ConditionalOnClass里面的name字段

于是我们听官方的建议,将starter调整如下

@Configuration
@EnableConfigurationProperties({ApolloRefreshProperties.class})
public class ApolloRefreshAutoConfiguration  {

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnClass(name = "com.ctrip.framework.apollo.ConfigService")
    public ApolloRefreshService apolloRefreshService(ApolloRefreshProperties properties) {
        return new ApolloRefreshService(properties);
    }
    }

再次运行,果然不再报错。具体问题原因,我就不班门弄斧了,可以查看官方的issue

总结

首先如果用 @ConditionalOnClass注解,强烈建议使用name属性,而不要用value属性。其次如果有提供组件给其他业务团队使用,要特别关注版本问题,以及做好向下兼容,不然指不定又掉坑了。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消