写在前面
接上一篇,同样的需求:需要写一个针对controller内参数的数据权限校验组件,所以需要想办法获取都某个对象的某个变量(可能跨层级)的值,所以研究和封装了一套可以使用的工具。这个工具类需要开发时定义好取值的路径,最终决定使用对参数注解,这样就可以针对单独参数的某个值进行权限校验。
开发思路:
1、在controller层的方法的参数上进行注解
2、为了提高拦截时的程序运行效率,项目启动时扫描所有注解的参数的方法放入缓存
3、aop拦截时进行判断是否需要存在于缓存,如有则进行权限校验
问题
写完了注解代码,然后决定使用BeanPostProcessor来进行controller方法的注解解析。
BeanPostProcessor应该很多人都了解,主要是对bean实例化前后的增强,实现了该接口后,主要流程如下
1 | ===Spring IOC容器实例化Bean=== |
所以我写了如下方法进行扫描,但是本以为顺理成章的流程却出现了问题,问题见注释
1 | //无关代码已省略 |
上面的错误经过多此debug排查终于找到原因:SpringAOP引起的。具体如下截图
可以看到图中标示处,beanObject的className为springCglib的动态代理类!所以通过反射拿到的class肯定不会有我们在controller里写的注解。
但是为什么bean实例对象是动态代理类呢?突然想起来之前用了AOP,如下
,设置了controller的切面来进行日志打印和输出,所以spring会自动帮我们把bean设置为动态代理后的实例。
找到了问题才可以对症下药
解决方案
1、如果不需要init初始化后置处理,则可以使用postProcessBeforeInitialization而非postProcessBeforeInitialization
2、实现Order接口,将order值set为AOP相关BeanPostProcessor的前面(具体原理后面几篇讲到)
3、寻找cglib内部结构,再通过java反射获取真实的代理对象(正在研究中,应该可以实现)