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


    前言

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

    @Configuration
    @EnableConfigurationProperties({ApolloRefreshProperties.class})
    public class ApolloRefreshAutoConfiguration  {
    
        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnClass({ConfigService.class})
        public ApolloRefreshService apolloRefreshService(ApolloRefreshProperties properties) {
            return new ApolloRefreshService(properties);
        }
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    该starter的pom引入的apollo gav是optional

      <dependency>
                <groupId>com.ctrip.framework.apollogroupId>
                <artifactId>apollo-clientartifactId>
                <version>${apollo-client.version}version>
                <optional>trueoptional>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    我的问题是

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

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

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

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

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

    问题排查

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

    他的大意是,可以在@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);
        }
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

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

    https://github.com/spring-projects/spring-boot/issues/27846

    https://github.com/spring-projects/spring-boot/issues/17282

    总结

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

  • 相关阅读:
    “维护者都快累死了!”Linux 宣布:LTS 版本的维护期,将从 6 年变回 2 年
    【PAT甲级】1131 Subway Map
    好物周刊#9:AI 学习必备资料
    招聘信息管理|基于SpringBoot招聘信息管理系统
    含有稀土元素Tb荧光磁性高分子微球/可聚合端基双键铕多元配位复合物荧光微球的研究
    操作系统与Java中线程状态的区分
    Redis 是什么和使用场景概述(技术选型)
    微服务(四)——zookeeper入门&api实践
    Python——正则表达式的应用
    解锁 DevOps 精通:成功的综合指南
  • 原文地址:https://blog.csdn.net/kingwinstar/article/details/132979588