你一定没遇到的AOP失效场景

老生常谈


	AOP 失效感觉老生常谈了 无非就是 @Transactional 注解用错位置 要不就是本类自身调用 导致 AOP 失效

遇到问题


	项目中个别 service 事务没有生效 于是开始对比 service 类和其他 service 有什么区别
	然并卵 找了个寂寞  

奇思妙想


	既然 AOP 在个别 service 层失效 那我把 AOP 放在 controller 层呢
	果然事务生效了 此次验证说明了 service 事务是没有问题的 
	有问题的是 service 层没有进行事务代理

分析原因


	通过观察项目启动控制台发现该 service 类在项目启动打印出了告警信息

	trationDelegate$BeanPostProcessorChecker : 
		Bean 'permissionServiceImpl' of type [xxx.xxx.service.impl.PermissionServiceImpl] 
		is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

	这句话意思是

	该BeanPostProcessorChecker就是输出上面那行信息的真凶,
	它会在Bean创建完后检查可在当前Bean上起作用的BeanPostProcessor个数与总的BeanPostProcessor个数,
	如果起作用的个数少于总数,则报出上面那句信息。

找出真凶


	问题原因已经浮出水面 该 service 没有被 spring 后置处理器所处理自然也就不会被代理进行事务拦截
	于是找到 该 service 引用的地方 发现 该 service 用在了配置 ShiroConfig 地方 ShiroConfig 里面配置了
	BeanPostProcessor 本身也是一个Bean,一般而言其实例化时机要早过普通的Bean,
	但是BeanPostProcessor也会依赖一些Bean,这就导致了一些Bean的实例化早于BeanPostProcessor,
	由此会导致一些问题 据此推断,可能是该 service 启动时机过早,导致的后面那些 BeanPostProcessor 们来没来得及实例化及注册呢。

继续深挖


	如果自定义类 implements BeanPostProcessor 
	还实现 Ordered 则不能被正常代理
	源码是先加载所有实现 Ordered 的 beanPostProcess 这其中包括 aop 的 process,
	会调用 beanFactory.getBean方法获取这个 process 对象,这会触发 bean 提前加载过程(遍历此时所有 process )
	很显然此时 beanFactory 还没有 aop 的 process,也就不能把对象进行 aop
	不实现 Ordered ,可以正常被代理
	源码是先加载所有实现 Ordered 的 process 类,这样一来容器就有 aop 的 process 了
	源码后加载没有实现 Ordered 的 process类
	源码详见 PostProcessorRegistrationDelegate.registerBeanPostProcessors(ConfigurableListableBeanFactory, AbstractApplicationContext)
	

问题解决


	说到底还是该死的 shiro 框架搞的鬼 没办法 遇到问题就需要解决 
	继承 AuthorizingRealm 类需要调用 service 去查询相关权限信息
	这里 service 就不会被代理 所以只好对该 service 进行懒加载
	用 @Lazy 进行标注 至此 AOP 事务恢复了
	业务中 implements BeanPostProcessor 处理业务逻辑千万不要 实现 Ordered 接口,
	不然里面引用的service事务会不生效
	非要实现order接口怎么办,注入的service加个 @Lazy

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值