Skip to content

希望支持 Jedis 3.x  #1647

Description

@prosaically

希望能够支持Jedis 3.x。

个人建议

ConfigStorage Jedis的实现构造应该统一使用WxRedisOps来构造,因为不使用统一会出现以下问题。

版本编号

  1. WxJava 3.8.0
  2. Jedis 3.2.0
  3. spring-boot-starter-data-redis 2.3

问题体现

异常环境

  1. Java JDK 1.8.0_201
  2. centos-release-7-6.1810.2.el7.centos.x86_64

环境差异

windows 10,jdk 1.8.0_171 下能正常运行。

代码实现

    @Bean
    public WxMpService wxMpService(StringRedisTemplate redis, WeChatConfig cfg) {
        RedisTemplateWxRedisOps ops = new RedisTemplateWxRedisOps(redis);
        WxMpRedisConfigImpl config = new WxMpRedisConfigImpl(ops, "wx");
        config.setAppId(cfg.getAppId());
        config.setSecret(cfg.getSecret());
        config.setToken(cfg.getToken());
        config.setAesKey(cfg.getEncodingAesKey());
        WxMpService wxService = new WxMpServiceImpl();
        wxService.setWxMpConfigStorage(config);
        return wxService;
    }

异常日志

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'wechatController': Unsatisfied dependency expressed through field 'wxMpServiceMap'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'wxMpService' defined in class path resource [com/egu365/api/config/WebConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [me.chanjar.weixin.mp.api.WxMpService]: Factory method 'wxMpService' threw exception; nested exception is java.lang.NoClassDefFoundError: redis/clients/util/Pool
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:895)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
	at com.egu365.api.Egu365RestApiApplication.main(Egu365RestApiApplication.java:19)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:109)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
	at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'wxMpService' defined in class path resource [com/egu365/api/config/WebConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [me.chanjar.weixin.mp.api.WxMpService]: Factory method 'wxMpService' threw exception; nested exception is java.lang.NoClassDefFoundError: redis/clients/util/Pool
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:656)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:636)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:1524)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1488)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeans(DefaultListableBeanFactory.java:1407)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1264)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1226)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
	... 28 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [me.chanjar.weixin.mp.api.WxMpService]: Factory method 'wxMpService' threw exception; nested exception is java.lang.NoClassDefFoundError: redis/clients/util/Pool
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651)
	... 44 common frames omitted
Caused by: java.lang.NoClassDefFoundError: redis/clients/util/Pool
	at com.egu365.api.config.WebConfig.wxMpService(WebConfig.java:212)
	at com.egu365.api.config.WebConfig$$EnhancerBySpringCGLIB$$14eddc6.CGLIB$wxMpService$22(<generated>)
	at com.egu365.api.config.WebConfig$$EnhancerBySpringCGLIB$$14eddc6$$FastClassBySpringCGLIB$$3f0fb69c.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
	at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331)
	at com.egu365.api.config.WebConfig$$EnhancerBySpringCGLIB$$14eddc6.wxMpService(<generated>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
	... 45 common frames omitted
Caused by: java.lang.ClassNotFoundException: redis.clients.util.Pool
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:129)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 56 common frames omitted

原因分析

使用Spring Data Redis,本生的目的是屏蔽Jedis客户端复杂和版本差异。

RedisTemplateWxRedisOps ops = new RedisTemplateWxRedisOps(template);

使用RedisTemplateWxRedisOps时,只要SpringDataRedis能正常运行,WxMpRedisConfigImpl也应该能正常运行。

  • 但由于windows 和linux下的jdk对class加载方式有差异。
 // 编号1
 // 未使用的构造
  public WxMpRedisConfigImpl(JedisPool jedisPool) {
    this(new JedisWxRedisOps(jedisPool), "wx");
  }
 // 编号2
 // 使用的构造器
  public WxMpRedisConfigImpl(WxRedisOps redisOps, String keyPrefix) {
    this.redisOps = redisOps;
    this.keyPrefix = keyPrefix;
  }

理论上来说,使用2号构造器,应该能正常使用,但是在Linux环境,Jdk确会加载1号构造器的依赖关系。
如果移除1号构造号,统一WxRedisOps来构造,就可以避免这样的问题。
WxMpRedisConfigImpl和JedisWxRedisOps(JedisPool jedisPool)没有直接依赖关系。也就不会去加载redis.clients.util.Pool。

  • 这样能够统一依赖,降压依赖的复杂程度。
  • 能够更加灵活,如果有特殊实现,也只需关注WxRedisOps接口。

_ 以上仅个人建议,希望项目越来越完善,成代码中最靓的仔 _

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions