current position:Home>Detailed explanation of spring AOP source code

Detailed explanation of spring AOP source code

2022-01-27 01:06:53 MiaSanMiaRL

Spring Two powerful features are IOC as well as AOP, We know Spring Realization AOP The process is in SpringBean Processing in post processor , stay Bean Execute at initialization time , Let's take a detailed look at how the source code is done

  The methods of generating proxy objects will be delegated to InvocationHandler.Proxy perform , Let's first look at JdkDynamicAopProxy in invoke Method implementation

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object oldProxy = null;
        boolean setProxyContext = false;
        TargetSource targetSource = this.advised.targetSource;
        Object target = null;

        Class var8;
        try {
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                Boolean var18 = this.equals(args[0]);
                return var18;
            }

            if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                Integer var17 = this.hashCode();
                return var17;
            }

            if (method.getDeclaringClass() != DecoratingProxy.class) {
                Object retVal;
                if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                    retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
                    return retVal;
                }

                if (this.advised.exposeProxy) {
                    oldProxy = AopContext.setCurrentProxy(proxy);
                    setProxyContext = true;
                }

                target = targetSource.getTarget();
                Class<?> targetClass = target != null ? target.getClass() : null;
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                if (chain.isEmpty()) {
                    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                    retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
                } else {
                    MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                    retVal = invocation.proceed();
                }

                Class<?> returnType = method.getReturnType();
                if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                    retVal = proxy;
                } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
                    throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
                }

                Object var12 = retVal;
                return var12;
            }

            var8 = AopProxyUtils.ultimateTargetClass(this.advised);
        } finally {
            if (target != null && !targetSource.isStatic()) {
                targetSource.releaseTarget(target);
            }

            if (setProxyContext) {
                AopContext.setCurrentProxy(oldProxy);
            }

        }

        return var8;
    }

Let's just look at a few important ways

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

Spring Realization AOP The responsibility chain model is used , And the function of this method is to obtain the chain

We can understand that , This chain is a collection of methods used to obtain and enhance the target object ( In order of execution ), If we get an empty chain , Then directly return to the original section , Return to the original object ; If so, trigger the interceptor chain ( The chain ) Implementation .

                    MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                    retVal = invocation.proceed();

Let's take another look proceed Method

    @Nullable
    public Object proceed() throws Throwable {
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return this.invokeJoinpoint();
        } else {
            Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
            if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
                InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
                Class<?> targetClass = this.targetClass != null ? this.targetClass : this.method.getDeclaringClass();
                return dm.methodMatcher.matches(this.method, targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
            } else {
                return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
            }
        }
    }

We all know that there are actually five links of enhancement methods on the target method

Namely : The rear notice 、 Return to inform 、 Abnormal notice 、 Surrounding the notification 、 Pre notice

The order in which they trigger execution , That is, the order of addition is

1、around

2、before

3、after

4、afterReturning

5、afterThrowing

our proceed Methods will first be in order , Determine whether we have configured the method of corresponding stage , If there is , Then execute the current enhancement method , without , The next method will be judged again through recursive call ; meanwhile , A count will be maintained on the chain , Used to manage the judged stage .

for instance

After we get the interceptor chain , First of all around Stage judgment

1、 We will first judge , stay around At this stage, I wonder if we have configured corresponding enhancement methods , here , Add one to the count of the chain , It means that we are about to enter the next stage of judgment .

2、 If in around There is an enhanced implementation of this method , Then execute the enhancement method .

3、 without , Recursively call proceed Method , Judgment of entering the next stage

Pay attention to this place , Here we use the judgment of recursive call into the method , in other words , After each stage of judgment , We'll go back to the interceptor chain , The interceptor tells us that we should enter that stage next time to judge .

The purpose of returning to the interceptor chain here is because we do not necessarily configure the enhancement methods in the established order in the configuration process , If the judgment is not specified by the interceptor chain , The sequence of stages will be disordered .

copyright notice
author[MiaSanMiaRL],Please bring the original link to reprint, thank you.
https://en.cdmana.com/2022/01/202201270106509345.html

Random recommended