• 【异常】because it is a JDK dynamic proxy that implements


    本文目录

    一、背景描述

    二、问题原因

    原因一:使用 @Resource 注解导致的问题

    原因三:注解配置缺少属性

    三、解决方案

    方案一:自动注入使用 @Autoware 注解

    方案二:仔细检查配置文件

    方案三:注解里添加必要的属性


    一、背景描述

    项目技术栈:Spring boot (2.1.5.RELEASE) + mqtt (5.1.5.RELEASE)

    项目是一个 Springboot 项目,集成了 EMQX,项目在启动时,提示应用启动失败,详情如下:

    1. ***************************
    2. APPLICATION FAILED TO START
    3. ***************************
    4. Description:
    5. The bean 'mqttSender' could not be injected as a 'com.iot.back.net.device.infrastructure.component.MqttMessageComponent' because it is a JDK dynamic proxy that implements:
    6. Action:
    7. Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies by setting proxyTargetClass=true on @EnableAsync and/or @EnableCaching.

    详细信息如图所示:

    二、问题原因

    原因一:使用 @Resource 注解导致的问题

    因为 @Autowired 默认按类型装配,而 @Resource 优先按名称装配。

    比如项目中存在一个 RedisTemplate bean,而由于需求的原因,又自定义了一个 RedisTemplate (比如切换 Redis 的数据库时),然后如果使用 @Resource 注解,由于项目中已经有另外一个 bean 叫 “RedisTemplate”,也可能出现这个错误。

    原因二:粗心导致

    比如基于 xml 的配置

    <bean id="powerSwtichService" class="com.xxx.xxx.xxx.xx.PowerSwtichService"/>

    这里的 class 并不是实际应该配置的:com.xxx.xxx.xxx.xx.PowerSwtichService

    原因三:注解配置缺少属性

    @EnableAsync、@EnableCaching 或者 @EnableAspectJAutoProxy 再或者 @EnableTransactionManagement 这些注解都可以设置 proxyTargetClass = true 属性

    主要配置基于 JDK 的代理还是基于类的动态代理的配置,这种错误提示需要设置基于类的代理才行。

    三、解决方案

    方案一:自动注入使用 @Autoware 注解

    此方案主要是针对原因一导致的问题而使用的解决方法,我项目里的解决方法就是使用方案一搞定的。

    1. @Slf4j
    2. @Component
    3. public class MusicQueryStateManager {
    4. @Autowired
    5. private MqttMessageComponent mqttMessageComponent;
    6. @Resource
    7. private HomeRpc homeRpc;
    8. @Resource
    9. private RedisTemplate redisTemplateDb16;
    10. public void handleDeviceAction(CommonControlParam controlParam) {
    11. log.info("E|MusicQueryStateManager|handleDeviceAction()|处理设备动作控制查询状态!controlParam = {}", JSONUtil.toJsonStr(controlParam));
    12. String hostSn = homeRpc.getHostSnByHomeSn(controlParam.getSn());
    13. String key = RedisKeyConstants.DEVICE_STATE + controlParam.getSn() + StrUtil.COLON + controlParam.getDeviceId();
    14. String value = redisTemplateDb16.opsForValue().get(key);
    15. DeviceStateDTO deviceStateDTO = JSONObject.parseObject(value, DeviceStateDTO.class);
    16. Assert.notNull(deviceStateDTO, "deviceStateDTO不能为空!");
    17. sendMessageToOpenPlatform(controlParam, hostSn, deviceStateDTO.getProperties());
    18. }
    19. /**
    20. * 发送消息给开放平台
    21. *
    22. * @param controlParam 控制请求参数
    23. * @param hostSn 主机sn
    24. */
    25. private void sendMessageToOpenPlatform(CommonControlParam controlParam, String hostSn, JSONObject properties) {
    26. String uuid = controlParam.getUuid();
    27. String topic = "thirdBgmusic/tgw_cloud/control/" + uuid + "/queryState";
    28. JSONObject data = new JSONObject();
    29. data.put("channel", 1);
    30. data.put("properties", properties);
    31. MqttMessagePublisher mqttPublisher = new MqttMessagePublisher.Builder()
    32. .title("背景音乐设备动作控制播放状态消息发送!")
    33. .topic(topic)
    34. .identity(hostSn)
    35. .clientType("tgw_host")
    36. .msgId(controlParam.getMsgId())
    37. .compression(CompressionEnum.ZLIB.getType())
    38. .encry(false)
    39. .data(data)
    40. .params(Params.create().set("sn", hostSn))
    41. .build();
    42. mqttMessageComponent.sendMessage(mqttPublisher);
    43. }
    44. }

    方案二:仔细检查配置文件

    比如 xml 配置文件,properties 配置文件,yml 配置文件等。

    方案三:注解里添加必要的属性

    比如:

    • @EnableAsync(proxyTargetClass = true) 或者
    • @EnableCaching(proxyTargetClass = true) 或者
    • @EnableAspectJAutoProxy(proxyTargetClass = true) 或者
    • @EnableTransactionManagement(proxyTargetClass = true)

    proxy-target-class 属性值决定是基于 JDK 接口还是基于类的代理被创建。

    • 如果为 true 代表基于类的代理,
    • 如果为 false 代表基于 JDK 接口的代理。

    如果 springboot 项目,也可以在配置文件里写上如下内容:

    spring.aop.proxy-target-class=true 

     

    完结!

  • 相关阅读:
    跨平台应用开发进阶(二十七)安卓应用加固签名后应用无法打开
    登陆认证&权限控制(1)——从session到token认证的变迁 & session的问题分析 + CSRF攻击的认识
    yolov5更换MobileNetV3的主干网络
    初学者理解递归
    【Java 基础篇】Java 接口组成与更新详解
    【SwiftUI模块】0008、SwiftUI-自定义启动闪屏动画-App启动闪屏曲线路径动画
    java中的IO流之序列化与反序列化(对象数据和文件的读写交互)
    Android 12 apk Installation did not succeed
    MySQL数据类型
    DS1302时钟芯片(SPI协议)
  • 原文地址:https://blog.csdn.net/weixin_44299027/article/details/126894949