OpenDaylight MDSAL:提取YANG模型特定Choice节点数据及处理代理类
解决YANG Choice节点Proxy类的数据获取问题
我之前也碰到过一模一样的问题,当时在处理OpenDaylight的DataChangeListener回调时,盯着这个com.sun.$Proxy类型愣了好久,后来摸索出几个实用的解决方法,分享给你:
方法一:直接强转为生成的Choice接口
YANG模型里的Choice节点在代码生成时,会对应生成一个接口(比如你的Choice叫user-selection,生成的接口可能是UserSelection),而那个$Proxy对象其实就是这个接口的动态代理实现。直接强转后,就能调用接口里的getter方法获取对应case的数据:
// 假设回调中获取到的DataObject是choiceData UserSelection choiceNode = (UserSelection) choiceData; // 调用对应case的getter,返回非null则说明当前是这个case生效 UserCaseA caseA = choiceNode.getUserCaseA(); if (caseA != null) { // 处理caseA里的具体数据,比如获取某个字段 String value = caseA.getMyField(); // ... 你的业务逻辑 } UserCaseB caseB = choiceNode.getUserCaseB(); if (caseB != null) { // 处理caseB的逻辑 }
这个方法最直接,只要你清楚Choice对应的接口名称,强转是完全安全的——因为代理类必然实现了这个生成的接口。
方法二:通过DataObject通用API动态遍历
所有生成的YANG绑定类都实现了org.opendaylight.yangtools.yang.binding.DataObject接口,你可以用它的通用方法来动态遍历Choice下的case,不需要提前知道具体的接口类型:
DataObject choiceProxy = ...; // 回调中拿到的Proxy对象 // 遍历Choice下的所有子节点(每个子节点对应一个case) for (DataObject childNode : choiceProxy.getChildren()) { // 判断子节点的类型来处理不同case if (childNode instanceof UserCaseA) { UserCaseA caseA = (UserCaseA) childNode; // 处理caseA逻辑 } else if (childNode instanceof UserCaseB) { UserCaseB caseB = (UserCaseB) childNode; // 处理caseB逻辑 } }
这个方法适合需要动态处理多个不同Choice节点的场景,不用硬编码接口名称。
方法三:结合InstanceIdentifier做类型安全转换
如果你的回调中能拿到InstanceIdentifier(也就是数据的路径),可以通过路径最后一个节点的类型来做安全强转,通用性更强:
InstanceIdentifier<?> dataPath = ...; // 回调中获取的路径 DataObject choiceData = ...; // 回调中获取的Proxy对象 // 获取Choice节点对应的类型 Class<? extends DataObject> choiceType = dataPath.lastNode().getType(); // 安全强转 DataObject choiceNode = choiceType.cast(choiceData); // 之后可以用方法一或方法二处理case数据
几个注意点
- 确保你的YANG代码是最新生成的:如果YANG模型有修改,一定要重新生成绑定代码,否则可能出现类型不匹配的问题。
- JDK动态代理的特性:
$Proxy类是JDK动态生成的,它会实现所有目标接口的方法,所以强转成生成的Choice接口不会有ClassCastException(只要类型对应)。
内容的提问来源于stack exchange,提问作者LostInTheFrequencyDomain
相关产品推荐
相关产品推荐

