Closed xiongxt86 closed 1 year ago
麻烦看一下使用的是不是最新版,之前有一个应该是类似的问题修复了,https://github.com/Adrninistrator/java-callgraph2/issues/30 如果是最新版的话,麻烦把上面的类的方法也发一下,方便看一点
已经是最新版本了;正式项目在远程桌面,没法复制;我本地构建一个类似的项目,生成文档对比,等会贴出来。
`
<artifactId>java-all-call-graph</artifactId>
<version>1.0.12</version>
</dependency>`
版本用的最新的1.0.12,仅仅修改了变量的名称(声明类型不变,仍然是接口),结果会有差异。 注入写法1: @Autowired private IUserService userServiceImpl;
com.macro.mall.dao.UserMapper:selectById(java.lang.String) [0]#UserMapper:selectById [1]# UserServiceImpl:queryById (UserServiceImpl:17) 这里接口调用没有融入到主链重 [2]# IUserService:queryById (IUserService:0) !entry! [2]# DeptServiceImpl:queryById (DeptServiceImpl:22) [3]# IDeptService:queryById (IDeptService:0) [4]# DeptController:queryById@io.swagger.annotations.ApiOperation@org.springframework.web.bind.annotation.RequestMapping(/dept/queryById)@org.springframework.web.bind.annotation.ResponseBody (DeptController:32) !entry!
注入写法2(结果正确的): @Autowired private IUserService userService;
com.macro.mall.dao.UserMapper:selectById(java.lang.String) [0]#UserMapper:selectById [1]# UserServiceImpl:queryById (UserServiceImpl:17) [2]# IUserService:queryById (IUserService:0) [3]# DeptServiceImpl:queryById (DeptServiceImpl:22) [4]# IDeptService:queryById (IDeptService:0) [5]# DeptController:queryById@io.swagger.annotations.ApiOperation@org.springframework.web.bind.annotation.RequestMapping(/dept/queryById)@org.springframework.web.bind.annotation.ResponseBody (DeptController:32) !entry!
有些场景声明类型是接口,仅仅变量名称恰好是spring工厂的bean对象,出现偏差了。
我看了另一个问题,他是根据名称找错接口了,我这个根据名称找对了接口,实现的spring对象也是对的,但多出了一个链路。
通过@Autowired注解注入的字段,注入的是接口的时候,之前有人希望能通过实现类找到对应的接口,所以在生成调用关系时没有把接口替换成实现类 要把调用关系里的接口替换成实现类是可以做到的,如果需要的话我增加一个参数来控制是否需要替换
文件清单: 1.DeptController.java
@Controller @Api(tags = "DeptController") @Tag(name = "DeptController", description = "Dept对象存储管理") @RequestMapping("/dept") public class DeptController {
@Autowired
private IDeptService deptService;
@ApiOperation("部门查询")
@RequestMapping(value = "/queryById", method = RequestMethod.POST)
@ResponseBody
public CommonResult<Object> queryById(@RequestParam("deptId") String deptId) {
try {
Dept dept = deptService.queryById(deptId);
return CommonResult.success(dept);
} catch (Exception e) {
e.printStackTrace();
}
return CommonResult.failed();
}
}
2.IDeptService.java public interface IDeptService {
public Dept queryById(String deptId);
}
3.DeptServiceImpl.java @Service public class DeptServiceImpl implements IDeptService {
@Autowired
private DeptMapper deptMapper;
@Autowired
private IUserService userService;
@Override
public Dept queryById(String deptId) {
userService.queryById(deptId);
return deptMapper.selectById(deptId);
}
} 4.IUserService.java public interface IUserService {
public User queryById(String userId);
} 5.UserServiceImpl.java @Service public class UserServiceImpl implements IUserService {
@Autowired
private UserMapper userMapper;
@Override
public User queryById(String userId) {
return userMapper.selectById(userId);
}
} 6.DeptMapper.java public interface DeptMapper { public Dept selectById(String deptId); } 7.UserMapper.java public interface UserMapper { public User selectById(String userId); }
可能误会我的意思了,不是把接口类替换为实现类;目前生成调用链是没有问题的,实现类->接口类->调用方实现类->调用方接口类; 问题出在,调用方注入被调用方声明变量时,名字换了个(由userService换成userServiceImpl),就会出错:《由一条调用链,变成了两条调用链》,我想要的效果是,变量的名字不管取啥(包括特例spring工厂的对象名,类似userServiceImpl),都只有一条调用链。
通过@Autowired注解注入的字段,注入的是接口的时候,之前有人希望能通过实现类找到对应的接口,所以在生成调用关系时没有把接口替换成实现类 要把调用关系里的接口替换成实现类是可以做到的,如果需要的话我增加一个参数来控制是否需要替换
使用@Autowired注解注入字段的时候,如果接口存在多个实现类,是可以通过字段的变量名来指定使用哪一个,Spring是这样实现的,现在分析代码的时候也是这么做的,所以上面的现象是和Spring特性一致的
如果需要解决的话可以有两种方法,一是像上面说的增加开关,决定是否需要把接口替换成实现类
二是获取到向上的方法调用的入口方法的时候,从数据库class_info
表的access_flags
字段判断当前类是否为接口,是接口就可以忽略掉,或者是通过这个表对应的文件记录来判断
大致描述:
预期仅有一条调用链(方式1调用链 ),但因为变量名字不规范就生成错误的调用关系。 猜测会优先通过变量名去获取spring工厂的实例,而忽略了声明的类型(接口)。