Цепной вызов spring aop

Java

Гуань Гуань Цзюйю, на речном континенте. Стройная дама, джентльмен хорош.

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/2/19/1690484302c4d39c~tplv-t2oaga2asx-image.image
https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/2/19/1690484302c4d39c~tplv-t2oaga2asx-image.image

Обзор

AOP(Aspect Orient Programming), которое мы обычно называем аспектно-ориентированным (аспектным) программированием, как дополнение к объектно-ориентированному, используется для решения сквозных задач, распределенных по различным модулям системы, таких как управление транзакциями, ведение журналов, кэширование и т. д. на.Spring AOPДинамический прокси используется для улучшения бизнес-методов во время выполнения, поэтому новые классы не создаются.Spring AOPпредусмотреноJDKПоддержка динамических прокси, а также поддержка CGLib. Мы не будем заострять внимание на этой главеaopДля реализации прокси-класса я просто реализую связанный вызов в указанном порядке.

реализовать цепной вызов

MethodInterceptorопределить цепочку перехватчиков,MethodInvocationРекурсивно введите следующую цепочку перехватчиков. Диаграмма классов выглядит следующим образом:

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/2/19/1690484302ab3847~tplv-t2oaga2asx-image.image
https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/2/19/1690484302ab3847~tplv-t2oaga2asx-image.image

MethodInterceptor

public interface MethodInterceptor {

    Object invoke(MethodInvocation invocation) throws Throwable;
}

MethodInvocation

public interface MethodInvocation {

    Object proceed() throws Throwable;
}

AbstractAspectJAdvice

Абстрактный класс, который реализуетMethodInterceptor

public abstract class AbstractAspectJAdvice implements MethodInterceptor{

    private Method adviceMethod;

    private Object adviceObject;

    public AbstractAspectJAdvice(Method adviceMethod, Object adviceObject) {
        this.adviceMethod = adviceMethod;
        this.adviceObject = adviceObject;
    }

    public Method getAdviceMethod() {
        return this.adviceMethod;
    }

    public void invokeAdviceMethod() throws Throwable {
        adviceMethod.invoke(adviceObject);
    }
}

AspectJBeforeAdvice

предварительное уведомление

public class AspectJBeforeAdvice extends AbstractAspectJAdvice {

    public AspectJBeforeAdvice(Method method, Object adviceObject) {
        super(method, adviceObject);
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable{
        this.invokeAdviceMethod();
        Object o = invocation.proceed();
        return o;
    }
}

AspectJAfterReturningAdvice

опубликовать уведомление

public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice {

    public AspectJAfterReturningAdvice(Method method, Object adviceObject) {
        super(method, adviceObject);
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable{
        Object o = invocation.proceed();
        this.invokeAdviceMethod();
        return o;
    }
}

ReflectiveMethodInvocation

выполнитьMethodInvocation,proceed()Метод рекурсивно реализует цепочку вызовов.

public class ReflectiveMethodInvocation implements MethodInvocation {

    private final Object targetObject;

    private final Method targetMethod;

    private final List<MethodInterceptor> interceptorList;

    private int currentInterceptorIndex = -1;

    public ReflectiveMethodInvocation(Object targetObject, Method targetMethod, List<MethodInterceptor> interceptorList) {
        this.targetObject = targetObject;
        this.targetMethod = targetMethod;
        this.interceptorList = interceptorList;
    }

    @Override
    public Object proceed() throws Throwable {

        if (this.currentInterceptorIndex == this.interceptorList.size() - 1) {
            return invokeJoinPoint();
        }

        this.currentInterceptorIndex++;

        MethodInterceptor interceptor =
                this.interceptorList.get(this.currentInterceptorIndex);
        return interceptor.invoke(this);
    }

    private Object invokeJoinPoint() throws Throwable {

        return this.targetMethod.invoke(this.targetObject);
    }
}

NioCoderService

моделированиеserviceДобрый

public class NioCoderService {

    public void testAop() {
        System.out.println("http://niocoder.com/");
    }
}

TransactionManager

Класс аналогового уведомления

public class TransactionManager {
    public void start() {
        System.out.println("start tx");
    }

    public void commit() {
        System.out.println("commit tx");
    }

    public void rollback() {
        System.out.println("rollback tx");
    }

}

ReflectiveMethodInvocationTest

beforeAdvice->afterReturningAdvice

тестовый класс, тестовое уведомление

public class ReflectiveMethodInvocationTest {

    private AspectJBeforeAdvice beforeAdvice = null;

    private AspectJAfterReturningAdvice afterReturningAdvice = null;

    private NioCoderService nioCoderService;

    private TransactionManager tx;

    public void setUp() throws Exception {
        nioCoderService = new NioCoderService();
        tx = new TransactionManager();
        beforeAdvice = new AspectJBeforeAdvice(TransactionManager.class.getMethod("start"), tx);
        afterReturningAdvice = new AspectJAfterReturningAdvice(TransactionManager.class.getMethod("commit"), tx);
    }

    public void testMethodInvocation() throws Throwable {
        Method method = NioCoderService.class.getMethod("testAop");
        List<MethodInterceptor> interceptorList = new ArrayList<>();
        interceptorList.add(beforeAdvice);
        interceptorList.add(afterReturningAdvice);        

        ReflectiveMethodInvocation mi = new ReflectiveMethodInvocation(nioCoderService, method, interceptorList);

        mi.proceed();
    }


    public static void main(String[] args) throws Throwable {
        ReflectiveMethodInvocationTest reflectiveMethodInvocationTest = new ReflectiveMethodInvocationTest();
        reflectiveMethodInvocationTest.setUp();
        reflectiveMethodInvocationTest.testMethodInvocation();
    }
}

выход:

start tx
http://niocoder.com/
commit tx
Диаграмма последовательности действий перед советом->после возврата совета

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/2/19/16904843029513d0~tplv-t2oaga2asx-image.image
https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/2/19/16904843029513d0~tplv-t2oaga2asx-image.image

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/2/19/1690484302f456e8~tplv-t2oaga2asx-image.image
https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/2/19/1690484302f456e8~tplv-t2oaga2asx-image.image

afterReturningAdvice->beforeAdvice

ИсправлятьinterceptorListЗаказ

  public void testMethodInvocation() throws Throwable {
        Method method = NioCoderService.class.getMethod("testAop");
        List<MethodInterceptor> interceptorList = new ArrayList<>();
        interceptorList.add(afterReturningAdvice);
		 interceptorList.add(beforeAdvice);

        ReflectiveMethodInvocation mi = new ReflectiveMethodInvocation(nioCoderService, method, interceptorList);

        mi.proceed();
    }

выход:

start tx
http://niocoder.com/
commit tx
Диаграмма последовательности действий после ReturningAdvice->beforeAdvice

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/2/19/1690484302fbb1c2~tplv-t2oaga2asx-image.image
https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/2/19/1690484302fbb1c2~tplv-t2oaga2asx-image.image

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/2/19/169048430309ea9f~tplv-t2oaga2asx-image.image
https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/2/19/169048430309ea9f~tplv-t2oaga2asx-image.image

загрузка кода

загрузка кода