controller层注入service为null,service使用Transactional注解 导致enhancerbyspringcglib问题
一、问题展现
项目都正常开发,突然有一天,发现某个同事写的contoller层注入service为null,但是部分controller又是正常的。并且有时候还会存在通过postman调用controller正常注入service,其他系统通过httpClient调用controller不能正常注入service。
二、问题调查
1、使用postman调用其他的controllerA 发现正常, 并且把同样的service注入到controllerA 正常注入 没有任何问题。
有个小插曲,中间还在spring-boot启动项上 打印出所有的bean 看看是否有两个对应的controllerW bean注入 然并没有
ApplicationContext ctx =SpringApplication.run(App.class, args);
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
java.util.Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
2、比较正常controllerA 与 不正常的controllerW 发现没有什么本质的区别,代码也基本上没有什么变动。 诡异中...
3、断点 分析 比较发现 不正常的controllerW 有个诡异问题,enhancerbyspringcglib 这时候真相已经隐藏在图中了 只是笨拙的我没有发现问题[email protected]@~
不正常图1
正常图2
4、区别在哪里 在哪里, enhancerbyspringcglib 网上搜索关键词 enhancerbyspringcglib
得到如下资料 a、https://blog.****.net/itrider/article/details/43634941
b、http://jinnianshilongnian.iteye.com/blog/1508018
c、http://jinnianshilongnian.iteye.com/blog/1508018
深入 Spring Boot:排查 @Transactional 引起的 NullPointerException
d、http://www.sohu.com/a/216425181_355142
5、整理了一下cglib代理 与 jdk动态代理的区别 等 controllerW上注入的service上确实有使用到注解
@Transactional(rollbackFor = PicaException.class) 以为如获至宝 然并暖用,只能说明是可能一个点 但肯定不 是这个问题引起的 因为controllerA 注入同样的service 没有问题的
6、 同时把所有的service中使用@Transactional 注解暂时注释掉 问题没有得到解决, 但是发现一个现象 这时候service 注入的方式改变了 如下图
这个现象暂时 不影响正常使用 可以暂时过一下 但 是不是跟controllerW 注入方式一样呢? 很像吧 这时候陷入死胡同 为什么??
7、陷入死胡同,这时候只能判断这个问题 controllerW的写法有问题,肯定做了什么见不得人的操作, 只能来代码比较 代码比较,询问当事人, 当事人回答,之前哪个日期点的代码是好的, 好好, 那就一点点代码回退,一点点代码比较, 问题终于重现了, 可以正常运行的代码 与 有问题的代码的时间节点 内容差异, 发现controllerW 方法体上用了 private修饰 再看一下其他 都是public 果断重现用public试一下 ok 问题得到解决
8、查找资料
a、https://blog.****.net/weixin_41633157/article/details/80083636
原因分析:
容器扫描bean生成代理类的时候,public和protected方法可以被正常代理,而private方法的不会被代理,属性的注入也是在代理类中完成,所以public/protected方法获取的注入属性是完成注入的属性,private方法获取的是未完成注入时的属性,所以是null
9、问题得到解决 但是走了不少弯路。
三、 总结
1、解决问题过程中,心态不够好,有点急躁
2、准确定位搜索关键词 这是个提炼能力的问题点。 如果直接搜索 “controller 方法private 导致注解丢失“ 明显很直接得 到答案
3、对spring bean注入 理解不到位。
原文出处 https://blog.****.net/sinat_41620463/article/details/82863661