Skip to content

希望支持 Jedis 3.x  #1647

Closed
Closed
@prosaically

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接口。

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions