前言

应用切面一段时间,写个根本切面没有问题。
然而这次应用切面时遇到了问题,发现切面没有执行,找谬误又无从找起,只能硬看代码。
大略代码是这样的

public class ImportExcelServiceImpl {    public void readFromFileAndSetAnswerSheets() {        ...        setAnswerSheet(currentRow);        ...    }        @UpdateAnswerSheetTotalNumber    public AnswerSheet setAnswerSheet(Row currentRow) {        ...        return answerSheet;    }}

这是被切办法

@Aspect@Componentpublic class UpdateAnswerSheetTotalNumberAspect {    @Pointcut("@annotation(....UpdateAnswerSheetTotalNumber)")    public void annotationPointCut() {    }        @AfterReturning(value = "annotationPointCut()", returning = "answerSheet")    public void after(AnswerSheet answerSheet) {        ...    }

这是切面

起因

找了半天找不进去哪里错了,就去问了老师,老师看出了问题所在。
原来我的被切办法是setAnswerSheet(),调用被切办法是通过this.setAnswerSheet()调用的,这就是对象内调用。而切面是基于代理模式,对象内调用办法是不走代理的,当然是不起作用的。

原来写的被切办法都是在一个对象中的办法调用另一个对象中的a办法的状况下。
此时spring会为被调用办法所在对象生成一个代理,此代理领有与服务雷同的办法,如果办法没有被执行切面,则在代理中间接将执行的办法转发给理论的服务,如果有切面,则会在代理中实现切面,这就是切面的原理。
咱们在类中打入断点

其中userServiceImpl.frozen使咱们的被切办法。注入的类名总是相似UserServiceImpl$$EnhancerBySpringCGLIB$$1c76af9d。为了让调用方取得UserServiceImpl的援用,它必须继承自UserServiceImpl。而后,该代理类会覆写所有publicprotected办法,并在外部将调用委托给原始的UserServiceImpl实例。~~~~

解决

解决的方法就是本人注入本人

class A {  @Autowired  A a;    public void test() {      // 这样应用切不到,是对象的外部调用    this->setXxx();        // 这样用就能够,因为注入的a实际上是a的代理    a->setXxx();  }    @Xxxxx  public xxx setXxx() {    }}

而这种依赖注入只能应用@Autowired的模式,不能应用构造函数的模式,构造函数模式会造成依赖注入的死循环。

总结

原来只会用AOP而不懂AOP的原理,认为他就如同@before的作用一样简略,直到遇到问题,能力了解aop的原理。