本文主要是介绍关于Spring增强器定义顺序引起的问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1 问题
org.springframework.beans.factory.BeanCreationException: Error creating bean with name'chat' defined in ServletContext resource[/WEB-INF/applicationContext_lease.xml]: Initialization of bean failed; nestedexception is java.lang.IllegalArgumentException: Advice precedence circularityerror
atorg.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at
...
Causedby: java.lang.IllegalArgumentException: Advice precedence circularityerror
atorg.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator.sortAdvisors(AspectJAwareAdvisorAutoProxyCreator.java:82)
atorg.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:90)
... 20 more
2 原因分析
反编译PartialOrder,发现只有在“List sort(List objects)”返回空时才会报错。 这个方法的作用是对增强器进行排序,排序的算法是从列表中每次查找最小值,把最小值写入objects的相应位置,然后重复该过程。查找最小值的算法是:先通过循环比较为每个增强器设置smallerObjects和biggerObjects两个列表,然后查找smallerObjects内容为空的。当查找最小增强器失败时,即所有增强器的smallerObjects都不为空时,就会返回null,从而导致上述异常。
所有增强器的比较规则(AspectJPrecedenceComparator):
1) 两个增强一个是after一个是before,那么返回0(相等)
2) 当其中一个是after时,按declareOrder进行比较,a1<a2,返回1,a1>a2,返回-1;(排在前面的大)
3) 不满足上面两个条件的,按declareOrder进行比较,a1<a2,返回-1,a1>a2,返回1。(排在后面的大)
declareOrder是clazz.getDeclaredMethod返回的方法的自然顺序,这个顺序在不同的jdk(编译、运行都有关)下是不同的,且在java的文档中明确说明返回的方法数组没有排序,也不承诺任何特别的顺序。
这样一来,比如有下面一组增强器,在jdk1.7下的顺序declareOrder如下:
Around1 order:1
After1 order:2
Around2 order:3
按照比较规则:
Around1 smallerObjects: After1
After1 smallerObjects: Around2
Around2 smallerObjects: Around1
这样所有增强器的smallerObjects都不为空,无法找到最小值,从而导致以上异常。
3 解决办法
把增强器拆分到不同的Aspect类中,比如把Around、After、Before分别放入不同的类,这样declareOrder就只是同一个类型的增强器的,也就不会出现上面的问题。
这篇关于关于Spring增强器定义顺序引起的问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!