Spring5源码13-AOP源码分析(下)创建代理和执行过程

2,173 阅读25分钟

首先我们需要知道的是,调用这个方法的是 createAopProxy() 方法的返回值,那么就可能是JdkDynamicAopProxy.getProxy 或者 ObjenesisCglibAopProxy.getProxy。下面我们来详细分析一下代理生成的过程。

5. JdkDynamicAopProxy

下面代码省略了JdkDynamicAopProxy 部分无关代码。

对于JDK 动态代理来说,实际调用代理方法是在 java.lang.reflect.InvocationHandler#invoke 中,因此 JdkDynamicAopProxy#invoke是我们的重点关注对象。

image.png

5.1 JdkDynamicAopProxy#getProxy

@Override
public Object getProxy() {
        return getProxy(ClassUtils.getDefaultClassLoader());
}

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
   if (logger.isTraceEnabled()) {
      logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
   }
   return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}

5.2 JdkDynamicAopProxy#invoke

@Override
@Nullable
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;

        try {
                // 处理 equals 方法
                if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                        // The target does not implement the equals(Object) method itself.
                        return equals(args[0]);
                }
                // 处理 hashCode 方法
                else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                        // The target does not implement the hashCode() method itself.
                        return hashCode();
                }
                // 处理 DecoratingProxy 类
                else if (method.getDeclaringClass() == DecoratingProxy.class) {
                        // There is only getDecoratedClass() declared -> dispatch to proxy config.
                        return AopProxyUtils.ultimateTargetClass(this.advised);
                }
                // 处理 Class类的isAssignableFrom(Class cls) 方法
                else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                                method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                        // Service invocations on ProxyConfig with the proxy config...
                        return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
                }

                Object retVal;
                // 是否暴露代理对象。有时候目标对象内部的自我调用将无法实施切面中的增强,则需要通过此属性暴露
                if (this.advised.exposeProxy) {
                        // Make invocation available if necessary.
                        oldProxy = AopContext.setCurrentProxy(proxy);
                        setProxyContext = true;
                }

                // Get as late as possible to minimize the time we "own" the target,
                // in case it comes from a pool.
                target = targetSource.getTarget();
                Class<?> targetClass = (target != null ? target.getClass() : null);

                // Get the interception chain for this method.
                //  获取当前方法的拦截链路,其中包括将AspectJMethodBeforeAdvice、AspectJAfterAdvice、AspectJAfterReturningAdvice 转换成合适的类型(InterceptorAndDynamicMethodMatcher)
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);


                if (chain.isEmpty()) {
                        // 拦截链路为空则直接调用切点方法
                        Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                        retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
                }
                else {
                        // We need to create a method invocation...
                        // 否则构建一个新的 方法调用对象 ReflectiveMethodInvocation
                        // 以便于使用proceed 方法进行链接表用拦截器
                        MethodInvocation invocation =
                                        new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                        // Proceed to the joinpoint through the interceptor chain.
                        // 调用方法,执行拦截器链路
                        retVal = invocation.proceed();
                }

                // Massage return value if necessary.
                // 返回结果
                Class<?> returnType = method.getReturnType();
                if (retVal != null && retVal == target &&
                                returnType != Object.class && returnType.isInstance(proxy) &&
                                !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                        // Special case: it returned "this" and the return type of the method
                        // is type-compatible. Note that we can't help if the target sets
                        // a reference to itself in another returned object.
                        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);
                }
                return retVal;
        }
        finally {
                if (target != null && !targetSource.isStatic()) {
                        // Must have come from TargetSource.
                        targetSource.releaseTarget(target);
                }
                if (setProxyContext) {
                        // Restore old proxy.
                        AopContext.setCurrentProxy(oldProxy);
                }
        }
}

上面我们有两个方法需要注意:

  • List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);。这一句将 获取当前方法的拦截链路,其中包括将AspectJMethodBeforeAdvice、AspectJAfterAdvice、AspectJAfterReturningAdvice 转换成 拦截器,用于后面的调用。

image.png

  • retVal = invocation.proceed(); : 对增强方法的调用

5.2.1 this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

我们讲了在 InstantiationModelAwarePointcutAdvisorImpl 中,Spring根据Aspect系列注解的不同将方法封装成了不同的Advice :AspectJAroundAdvice、AspectJMethodBeforeAdvice、AspectJAfterAdvice、AspectJAfterReturningAdvice、AspectJAfterThrowingAdvice

invocation.proceed() 的分析中我们会发现最终调用的增强方法为 MethodInterceptor#invoke方法。但是在上述五个Advice 中,只有AspectJAroundAdviceAspectJAfterAdvice 实现了MethodInterceptor 接口,其余的并没有实现 MethodInterceptor 接口,那么这时候就需要进行一个转换,将 Advice 转换成 MethodInterceptor 类型,该转换就是在此方法中完成。

由于 this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 方法最终会调用DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice,所以我们这里直接看该方法

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
                Advised config, Method method, @Nullable Class<?> targetClass) {

        // This is somewhat tricky... We have to process introductions first,
        // but we need to preserve order in the ultimate list.
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
        Advisor[] advisors = config.getAdvisors();
        List<Object> interceptorList = new ArrayList<>(advisors.length);
        Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
        Boolean hasIntroductions = null;

        for (Advisor advisor : advisors) {
                // 我们这里的Advisor 都是 PointcutAdvisor 所以这里只分析该内容
                if (advisor instanceof PointcutAdvisor) {
                        // Add it conditionally.
                        PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;

                        if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                                boolean match;
                                if (mm instanceof IntroductionAwareMethodMatcher) {
                                        if (hasIntroductions == null) {
                                                hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
                                        }
                                        match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
                                }
                                else {
                                        match = mm.matches(method, actualClass);
                                }
                                //如果代理规则与当前类匹配
                                if (match) {
                                        // 进行转化注册
                                        MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                                        if (mm.isRuntime()) {
                                                // Creating a new object instance in the getInterceptors() method
                                                // isn't a problem as we normally cache created chains.
                                                for (MethodInterceptor interceptor : interceptors) {
                                                        // 封装成 InterceptorAndDynamicMethodMatcher
                                                        interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                                                }
                                        }
                                        else {
                                                interceptorList.addAll(Arrays.asList(interceptors));
                                        }
                                }
                        }
                }
                else if (advisor instanceof IntroductionAdvisor) {
                        IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
                        if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
                                Interceptor[] interceptors = registry.getInterceptors(advisor);
                                interceptorList.addAll(Arrays.asList(interceptors));
                        }
                }
                else {
                        Interceptor[] interceptors = registry.getInterceptors(advisor);
                        interceptorList.addAll(Arrays.asList(interceptors));
                }
        }
        // 返回最终的拦截器集合
        return interceptorList;
}

我们可以看到关键的代码就是 registry.getInterceptors(advisor);,所以我们这里来看 DefaultAdvisorAdapterRegistry#getInterceptors 的 实现,其目的是将所有的Advisor中的Advice 转换成 MethodInterceptor

@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
        List<MethodInterceptor> interceptors = new ArrayList<>(3);
        Advice advice = advisor.getAdvice();
        // 如果 Advice 就是MethodInterceptor 类型,则直接保存
        if (advice instanceof MethodInterceptor) {
                interceptors.add((MethodInterceptor) advice);
        }
        // 否则寻找合适的适配器进行转换。
        // 这里的适配器有三个,分别是`AfterReturningAdviceAdapter`、`MethodBeforeAdviceAdapter`、`ThrowsAdviceAdapter`
        for (AdvisorAdapter adapter : this.adapters) {
                if (adapter.supportsAdvice(advice)) {
                        interceptors.add(adapter.getInterceptor(advisor));
                }
        }
        if (interceptors.isEmpty()) {
                throw new UnknownAdviceTypeException(advisor.getAdvice());
        }
        return interceptors.toArray(new MethodInterceptor[0]);
}

这里的适配器有三个,分别是AfterReturningAdviceAdapter、MethodBeforeAdviceAdapter、ThrowsAdviceAdapter。很明显就是为了上面的三个Advice类型准备的。经历过此步骤,所有的Advice 都转换为了 MethodInterceptor。我们这里挑选其中一个ThrowsAdviceAdapter 看:

class ThrowsAdviceAdapter implements AdvisorAdapter, Serializable {

    @Override
    public boolean supportsAdvice(Advice advice) {
            return (advice instanceof ThrowsAdvice);
    }

    @Override
    public MethodInterceptor getInterceptor(Advisor advisor) {
            return new ThrowsAdviceInterceptor(advisor.getAdvice());
    }

}

逻辑很简答,就是将 ThrowsAdvice 封装成了ThrowsAdviceInterceptor。其他两个以此类推。

5.2.2 retVal = invocation.proceed();

我们来看看 ReflectiveMethodInvocation#proceed 的实现,上面说过增强方法的调用实际上是在此完成的。

public Object proceed() throws Throwable {
        // We start with an index of -1 and increment early.
        // 如果所有的增强器已经执行完了,则调用实际方法
        // interceptorsAndDynamicMethodMatchers 是在2.2.1 中解析出来的动态拦截器集合
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
                // 这里调用了真正的方法  通过Method.invoke 方法
                return invokeJoinpoint();
        }
        // 获取下一个要调用的增强拦截器
        Object interceptorOrInterceptionAdvice =
                        this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
                // Evaluate dynamic method matcher here: static part will already have
                // been evaluated and found to match.
                // 动态匹配
                InterceptorAndDynamicMethodMatcher dm =
                                (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
                Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
                // 如果当前增强匹配当前的方法,则调用增强
                if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
                        // 调用 拦截器的 invoke 方法
                        return dm.interceptor.invoke(this);
                }
                else {
                        // Dynamic matching failed.
                        // Skip this interceptor and invoke the next in the chain.
                        // 不匹配则不执行拦截器,递归调用,遍历下一个拦截器
                        return proceed();
                }
        }
        else {
                // It's an interceptor, so we just invoke it: The pointcut will have
                // been evaluated statically before this object was constructed.
                // 普通的拦截器,直接调用拦截器。我们一般都走这里
                // 将this 作为参数传递以保证当前实力中的调用链路的执行
                // 直接调用 Advice 的 invoke 方法
                return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
}

欢迎大家关注 github.com/hsfxuebao ,希望对大家有所帮助,要是觉得可以的话麻烦给点一下Star哈

ReflectiveMethodInvocation#process 方法中的逻辑并不复杂。ReflectiveMethodInvocation 中的主要职责是维护了链接调用的计数器,记录着当前调用链接的位置,以便链可以有序的进行下去,在这个方法中并没有维护各种增强的顺序,而是将此工作委托给了各个增强器,使各个增强器在内部进行逻辑实现。

5.3 总结

JdkDynamicAopProxy#invoke 方法中:

  • 首先处理equals 和hashcode 等方法。

  • 随后调用 this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 方法将获取到拦截器。

  • 因为Jdk动态代理在调用增强方法时,是通过 MethodInterceptor#invoke 方法来调用,但对于AspectJAroundAdvice、AspectJMethodBeforeAdvice、AspectJAfterAdvice、AspectJAfterReturningAdvice、AspectJAfterThrowingAdvice来说,只有AspectJAroundAdviceAspectJAfterAdvice 实现了MethodInterceptor 接口,其余的并没有实现 MethodInterceptor 接口。所以在 registry.getInterceptors(advisor) 中,将Advisor中的 Advice 都封装成 MethodInterceptor,以便后面方法增强调用。

  • 随后MethodInterceptor 封装成 InterceptorAndDynamicMethodMatcher,其实就是一个简单的封装,以便后面处理。 关于 InterceptorAndDynamicMethodMatcher 的实现如下 ,可以看到其逻辑很简单:

class InterceptorAndDynamicMethodMatcher {
	// MethodInterceptor  方法拦截器,这里保存了针对于该方法的增强实现
	final MethodInterceptor interceptor;
	// 方法匹配器,用来匹配当前拦截器是否适用于当前方法
	final MethodMatcher methodMatcher;

	public InterceptorAndDynamicMethodMatcher(MethodInterceptor interceptor, MethodMatcher methodMatcher) {
		this.interceptor = interceptor;
		this.methodMatcher = methodMatcher;
	}

}

至此,@Aspect 系列注解修饰的方法从 Advisor 转换成了 InterceptorAndDynamicMethodMatcher

在调用invocation.proceed();方法时,针对 InterceptorAndDynamicMethodMatcher 类型,会通过InterceptorAndDynamicMethodMatcher#methodMatcher 判断是否适用于当前方法,如果适用则调用InterceptorAndDynamicMethodMatcher#interceptorinvoke 方法来执行增强方法。

6. Cglib 的代理过程

我们来看一下 cglib 动态代理。

6.1. org.springframework.cglib.proxy.Callback

callback可以认为是cglib用于生成字节码的实现手段,cglib一共实现了6种callback,用于对代理类目标进行不同手段的代理,非常灵活,具体如下:

  • Dispatcher :实现Dispatcher接口,要求实现loadObject方法,返回期望的代理类。值的一提的是,loadobject方法在每次调用被拦截方法的时候都会被调用一次。

  • FixedValue :实现FixedValue接口,该callback同样要求实现一个loadobject方法,只不过需要注意的是该loadobject方法相同与重写了被代理类的相应方法,因为在被代理之后,FixedValue callback只会调用loadobject,而不会再调用代理目标类的相应方法!

  • InvocationHandler :需要实现InvocationHandler接口,实现invoke对象,该拦截传入了proxy对象,用于自定义实现,与MethodInterceptor相似,慎用method的invoke方法。切忌不要造成循环调用

  • LazyLoader :实现LazyLoader的loadObject方法,返回对象实例,该实例只有第一次调用的时候进行初始化,之后不再重新调用,proxy类初始化时进行了成员的赋值,之后使用该成员进行调用父类方法

  • MethodInterceptor :实现MethodInterceptor的intercept,实现被代理对象的逻辑植入。也是最常用的callback

  • NoOp :通过接口声明了一个单例对象,该代理不对被代理类执行任何操作

6.2 代理对象的创建

Spring Aop 的代理对象创建在 CglibAopProxy#getProxy(java.lang.ClassLoader) 中完成。其实现如下:

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
        try {
                Class<?> rootClass = this.advised.getTargetClass();
                Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

                Class<?> proxySuperClass = rootClass;
                // 如果当前类名中包含 “$$” 则被认定为是 cglib 类。
                if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
                        proxySuperClass = rootClass.getSuperclass();
                        Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                        for (Class<?> additionalInterface : additionalInterfaces) {
                                this.advised.addInterface(additionalInterface);
                        }
                }

                // Validate the class, writing log messages as necessary.
                // 校验方法的合法性,但仅仅打印了日志
                validateClassIfNecessary(proxySuperClass, classLoader);

                // Configure CGLIB Enhancer...
                // 配置 Enhancer
                Enhancer enhancer = createEnhancer();
                if (classLoader != null) {
                        enhancer.setClassLoader(classLoader);
                        if (classLoader instanceof SmartClassLoader &&
                                        ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                                enhancer.setUseCache(false);
                        }
                }
                enhancer.setSuperclass(proxySuperClass);
                enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
                enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
                enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
                // 1. 获取代理的回调方法集合
                Callback[] callbacks = getCallbacks(rootClass);
                Class<?>[] types = new Class<?>[callbacks.length];
                for (int x = 0; x < types.length; x++) {
                        types[x] = callbacks[x].getClass();
                }
                // fixedInterceptorMap only populated at this point, after getCallbacks call above
                // 2. 添加 Callback 过滤器。
                enhancer.setCallbackFilter(new ProxyCallbackFilter(
                                this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
                enhancer.setCallbackTypes(types);

                // Generate the proxy class and create a proxy instance.
                // 创建代理对象
                return createProxyClassAndInstance(enhancer, callbacks);
        }
        ...
}

这里我们知道 CglibAopProxy#getCallbacks 会返回一个Callback集合,而 Cglib 的代理对象是通过 ProxyCallbackFilter 中的策略来确定什么场景下使用不同的 Callback

因此下面我们来看一下这两个类的具体实现:

6.2.1 CglibAopProxy#getCallbacks

CglibAopProxy#getCallbacks 是生成代理类的 Callback。具体实现如下:

// 上面可以很明显知道,CallBack是代理增强的关键实现。
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
        // Parameters used for optimization choices...
        // 是否暴露代理类
        boolean exposeProxy = this.advised.isExposeProxy();
        // 是否被冻结
        boolean isFrozen = this.advised.isFrozen();
        // 是否静态类,这里的静态并非指静态类,而是每次调用返回的实例都是否是不可变的
        // 如单例模式的bean就是静态,而多例模式下的bean就不是静态
        boolean isStatic = this.advised.getTargetSource().isStatic();

        // Choose an "aop" interceptor (used for AOP calls).
        // 创建 Aop 拦截器
        Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

        // Choose a "straight to target" interceptor. (used for calls that are
        // unadvised but can return this). May be required to expose the proxy.
        Callback targetInterceptor;
        // 根据是否包括和 静态,来生成不同的拦截器
        if (exposeProxy) {
                targetInterceptor = (isStatic ?
                                new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
                                new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
        }
        else {
                targetInterceptor = (isStatic ?
                                new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
                                new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
        }

        // Choose a "direct to target" dispatcher (used for
        // unadvised calls to static targets that cannot return this).
        Callback targetDispatcher = (isStatic ?
                        new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
        // 回调集合。其中包含aopInterceptor 中包含了 Aspect 的增强
        //  advisedDispatcher 用于判断如果method是Advised.class声明的,则使用AdvisedDispatcher进行分发
        Callback[] mainCallbacks = new Callback[] {
                        aopInterceptor,  // for normal advice
                        targetInterceptor,  // invoke target without considering advice, if optimized
                        new SerializableNoOp(),  // no override for methods mapped to this
                        targetDispatcher, this.advisedDispatcher,
                        new EqualsInterceptor(this.advised),
                        new HashCodeInterceptor(this.advised)
        };

        Callback[] callbacks;
        // 如果类是静态 && 配置冻结。则准备做一些优化策略
        if (isStatic && isFrozen) {
                Method[] methods = rootClass.getMethods();
                Callback[] fixedCallbacks = new Callback[methods.length];
                this.fixedInterceptorMap = new HashMap<>(methods.length);

                // TODO: small memory optimization here (can skip creation for methods with no advice)
                // 遍历所有的方法
                for (int x = 0; x < methods.length; x++) {
                        Method method = methods[x];
                        // 获取适用于当前方法的拦截器和动态拦截建议
                        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
                        // 封装成  callback
                        fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
                                        chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
                        // 保存,此时的key 为 method, value 为当前方法适用的增强。
                        this.fixedInterceptorMap.put(method, x);
                }

                // Now copy both the callbacks from mainCallbacks
                // and fixedCallbacks into the callbacks array.
                callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
                System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
                System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
                this.fixedInterceptorOffset = mainCallbacks.length;
        }
        else {
                callbacks = mainCallbacks;
        }
        return callbacks;
}

这里我们注意 Callback数组的组成:Callback数组是由 mainCallbacks + fixedInterceptorMap 组成。mainCallbacks 数组如下,为固定的七个。具体我们后面分析。

    Callback[] mainCallbacks = new Callback[] {
                    aopInterceptor,  // for normal advice
                    targetInterceptor,  // invoke target without considering advice, if optimized
                    new SerializableNoOp(),  // no override for methods mapped to this
                    targetDispatcher, this.advisedDispatcher,
                    new EqualsInterceptor(this.advised),
                    new HashCodeInterceptor(this.advised)
    };
  • fixedInterceptorMapSpring 在静态类 和 配置冻结情况下所做的优化。当类是静态类则表示当前类单例 && 配置冻结则表示配置不会变动。那么此时方法的拦截器可以提前获取并保存到 FixedChainStaticTargetInterceptor 中。ProxyCallbackFilter 中判断如果method 在 fixedInterceptorMap 中存在,则可以直接从 fixedInterceptorMap 中获取到适用于该方法的增强,而不需要再次查找。

这里的所说的静态是 根据 TargetSource#isStatic 方法判断,标志用户返回当前bean是否为静态的,比如常见的单例bean就是静态的,而原型模式下就是动态的。这里这个方法的主要作用是,对于静态的bean,spring是会对其进行缓存的,在多次使用TargetSource获取目标bean对象的时候,其获取的总是同一个对象,通过这种方式提高效率。

6.2.2 ProxyCallbackFilter

ProxyCallbackFilterCglibAopProxy 的内部类,用来作为 Cglib CallBack 过滤器,在不同的场景下选择不同的 Callback执行增强策略。下面我们来看看 ProxyCallbackFilter#accept 的具体实现 :

// Constants for CGLIB callback array indices
// 这里是 Callback 数组的下标。
private static final int AOP_PROXY = 0;
private static final int INVOKE_TARGET = 1;
private static final int NO_OVERRIDE = 2;
private static final int DISPATCH_TARGET = 3;
private static final int DISPATCH_ADVISED = 4;
private static final int INVOKE_EQUALS = 5;
private static final int INVOKE_HASHCODE = 6;

private static class ProxyCallbackFilter implements CallbackFilter {
// 返回是 Callback 数组的下标
@Override
public int accept(Method method) {
        // 1. 如果当前方法被 final 修饰,则不代理该方法
        if (AopUtils.isFinalizeMethod(method)) {
                logger.trace("Found finalize() method - using NO_OVERRIDE");
                return NO_OVERRIDE;
        }
        // 2. 如果当前方法不透明 && 该方法是 Advised 接口声明的方法
        if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
                        method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                return DISPATCH_ADVISED;
        }
        // We must always proxy equals, to direct calls to this.
        // 3. equals 方法 
        if (AopUtils.isEqualsMethod(method)) {
                return INVOKE_EQUALS;
        }
        // We must always calculate hashCode based on the proxy.
        // 4. hashcode 方法
        if (AopUtils.isHashCodeMethod(method)) {
                return INVOKE_HASHCODE;
        }
        // 获取代理目标类的 Class
        Class<?> targetClass = this.advised.getTargetClass();
        // Proxy is not yet available, but that shouldn't matter.
        // 获取适用于当前类的 拦截器和动态拦截建议
        List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
        boolean haveAdvice = !chain.isEmpty();
        boolean exposeProxy = this.advised.isExposeProxy();
        boolean isStatic = this.advised.getTargetSource().isStatic();
        boolean isFrozen = this.advised.isFrozen();
        // 5. 如果存在适用于当前类的拦截器和建议 || 配置没有被冻结
        if (haveAdvice || !isFrozen) {
                // If exposing the proxy, then AOP_PROXY must be used.
                // 5.1 暴露代理类
                if (exposeProxy) {
                        return AOP_PROXY;
                }
                // 5.2 类为静态 && 配置冻结 && 固定拦截器中保存了该方法的配置
                // 检查是否有固定的拦截器来服务这个方法, 这里使用了 fixedInterceptorMap 做了一些优化
                // fixedInterceptorMap  key 为 Method, value 为 Integer 保存了拦截器下标。这里针对某些方法固定使用某个拦截器,不需要再动态匹配。
                if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(method)) {
                        int index = this.fixedInterceptorMap.get(method);
                        return (index + this.fixedInterceptorOffset);
                }
                else {
                        // 5.3 否则还是使用 AOP_PROXY
                        return AOP_PROXY;
                }
        }
        else {// 6. 到这里说明当前方法没有建议 && 配置冻结

                // 6.1. 暴露当前代理类 && 代理类不是静态
                if (exposeProxy || !isStatic) {
                        return INVOKE_TARGET;
                }
                // 6.2. 如果方法返回类型还是代理类类型
                Class<?> returnType = method.getReturnType();
                if (targetClass != null && returnType.isAssignableFrom(targetClass)) {
                        return INVOKE_TARGET;
                }
                else {
                        // 6.3 DISPATCH_TARGET
                        return DISPATCH_TARGET;
                }
        }
}

这里总结如下:

  1. 如果method 被 final 修饰,则无法代理,返回 2 ,执行 SerializableNoOp,即代理不会做任何事。
  2. 如果 method 是 Advised 接口声明的方法,返回 4。执行AdvisedDispatcher
  3. 如果 method 是 equals 方法,返回 5, 执行 EqualsInterceptor
  4. 如果 method 是 hashCode 方法,返回 6,执行 HashCodeInterceptor
  5. 如果存在当前方法的拦截器或动态建议 || 配置未冻结 :
      1. 如果需要暴露代理对象,返回 0。执行 DynamicAdvisedInterceptor。这是常规的逻辑
      1. 如果 类静态 && 配置冻结 && fixedInterceptorMap 中缓存了该方法,则使用 fixedInterceptorMap 中的 Callback,返回计算出来的下标。执行的是在 CglibAopProxy#getCallbacks中包装的 FixedChainStaticTargetInterceptor 类型
      1. 不满足5.2 的情况执行返回0。执行 DynamicAdvisedInterceptor。这是常规的逻辑
  6. 如果不存在当前方法的拦截器或动态建议 && 配置已经冻结 :
      1. 如果需要暴露代理对象 || 对象非静态 ,返回1。这里根据情况的不同可以为StaticUnadvisedExposedInterceptor、DynamicUnadvisedExposedInterceptor、StaticUnadvisedInterceptor、DynamicUnadvisedInterceptor,本质上没有多少区别,主要是对 exposeProxy 属性的处理
      1. 如果代理对象类型派生于 方法返回类型,返回 1。同上
    • 3.不满足6.2 返回 3。如果是静态类执行 StaticDispatcher, 否则执行 SerializableNoOp。

6.3 Cglib 的拦截器

上面我们看到 Cglib 默认的 mainCallbacks 如下:

    Callback[] mainCallbacks = new Callback[] {
                    aopInterceptor,  // for normal advice
                    targetInterceptor,  // invoke target without considering advice, if optimized
                    new SerializableNoOp(),  // no override for methods mapped to this
                    targetDispatcher, this.advisedDispatcher,
                    new EqualsInterceptor(this.advised),
                    new HashCodeInterceptor(this.advised)
    };

下面我们逐一来看:

6.3.1 aopInterceptor

aopInterceptor 的实现类是 DynamicAdvisedInterceptor,实现了MethodInterceptor 接口 用来处理常规的代理逻辑。结构如下:

image.png

我们直接来看看 DynamicAdvisedInterceptor#intercept 的具体实现,如下:

@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object oldProxy = null;
        boolean setProxyContext = false;
        Object target = null;
        // 获取目标数据
        TargetSource targetSource = this.advised.getTargetSource();
        try {
                // 如果暴露代理对象,则设置到全局上下文中
                if (this.advised.exposeProxy) {
                        // Make invocation available if necessary.
                        oldProxy = AopContext.setCurrentProxy(proxy);
                        setProxyContext = true;
                }
                // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
                // 获取目标对象
                target = targetSource.getTarget();
                Class<?> targetClass = (target != null ? target.getClass() : null);
                // 1. 获取 适用于当前类的当前方法的 获取拦截器和动态拦截建议
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                Object retVal;
                // 如果没有建议链则说明对该方法不需要增强,直接调用即可
                if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                        // 即当前 args 的参数类型可能与实际方法调用的类型有些区别,这里转换成实际方法的参数类型。特别是,如果给定的可变参数数组与方法中声明的可变参数的数组类型不匹配。
                        Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                        // 调用目标类的目标方法
                        retVal = methodProxy.invoke(target, argsToUse);
                }
                else {
                        // We need to create a method invocation...
                        // 2. 创建一个 方法调用类,里面封装了相关信息,然后通过 proceed 方法调用
                        retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
                }
                // 处理返回值。 即,如果返回值还是 target。则替换为 代理的proxy
                retVal = processReturnType(proxy, target, method, retVal);
                return retVal;
        }
        finally {
                if (target != null && !targetSource.isStatic()) {
                        targetSource.releaseTarget(target);
                }
                if (setProxyContext) {
                        // Restore old proxy.
                        AopContext.setCurrentProxy(oldProxy);
                }
        }
}

注释已经写的比较清楚,这里我们关注下面两点:

  • this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass) : 这里的 this.advised 实现是 ProxyFactory
  • new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed() :这里的 CglibMethodInvocation#proceed 方法完成了拦截器链的调用。

1. ProxyFactory#getInterceptorsAndDynamicInterceptionAdvice

ProxyFactory#getInterceptorsAndDynamicInterceptionAdvice 是获取当前方法的 拦截器和动态拦截建议,在上面也多次调用。其实现在 AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice 中,如下:

// 当前 this 为 ProxyFactory,所以这里的缓存是作用域是在 ProxyFactory中,如果换一个 ProxyFactory则需要重新加载一次。
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
        // 生成方法的key
        MethodCacheKey cacheKey = new MethodCacheKey(method);
        // 从缓存中获取该方法的 拦截器和动态拦截建议
        List<Object> cached = this.methodCache.get(cacheKey);
        if (cached == null) {
                // 缓存没有命中则重新获取
                cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
                                this, method, targetClass);
                // 将获取到的 拦截器和动态拦截建议 放入缓存中。
                this.methodCache.put(cacheKey, cached);
        }
        return cached;
}

这里的 this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice 调用的是 DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice,其实现如下:

@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
                Advised config, Method method, @Nullable Class<?> targetClass) {

        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
        Advisor[] advisors = config.getAdvisors();
        List<Object> interceptorList = new ArrayList<>(advisors.length);
        Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
        Boolean hasIntroductions = null;
        // 遍历所有的 Advisor,这里的 Advisor 是 ProxyFactory 中保存的
        for (Advisor advisor : advisors) {
                /******* 1. PointcutAdvisor 顾问类型的处理 *******/
                // 如果是切点顾问
                if (advisor instanceof PointcutAdvisor) {
                        // Add it conditionally.
                        PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                        // 如果经过 预过滤 || 当前顾问 匹配当前类
                        if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                                // 判断当前方法是否匹配
                                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                                boolean match;
                                if (mm instanceof IntroductionAwareMethodMatcher) {
                                        if (hasIntroductions == null) {
                                                hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
                                        }
                                        match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
                                }
                                else {
                                        match = mm.matches(method, actualClass);
                                }
                                // 如果方法也匹配,则认为当前顾问适用于当前方法
                                if (match) {
                                        // 获取顾问中的 方法拦截器。这里会将部分不合适的类型转换为合适的拦截器
                                        MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                                        // runtime 为 true, 表明是动态调用,即每次调用都需要执行一次判断。
                                        if (mm.isRuntime()) {
                                                // 动态调用将 拦截器包装成 InterceptorAndDynamicMethodMatcher
                                                for (MethodInterceptor interceptor : interceptors) {
                                                        interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                                                }
                                        }
                                        else {
                                                // 否则直接添加
                                                interceptorList.addAll(Arrays.asList(interceptors));
                                        }
                                }
                        }
                }
                else if (advisor instanceof IntroductionAdvisor) {
                        /******* 2. IntroductionAdvisor 顾问类型的处理 *******/
                        // 如果是引介顾问类型
                        IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
                        // 预过滤 || 调用类匹配
                        if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
                                // 直接添加
                                Interceptor[] interceptors = registry.getInterceptors(advisor);
                                interceptorList.addAll(Arrays.asList(interceptors));
                        }
                }
                else {
                        /******* 3. 其他顾问类型的处理 *******/
                        // 直接添加
                        Interceptor[] interceptors = registry.getInterceptors(advisor);
                        interceptorList.addAll(Arrays.asList(interceptors));
                }
        }
        // 返回拦截器集合
        return interceptorList;
}

上面的逻辑还是比较清楚,如下:

  1. 遍历 当前 ProxyFactory 中所有的顾问 Advisor 集合。这个Advisor 集合来自于 AbstractAutoProxyCreator#createProxy 中的设值。
  2. 下面会根据 Advisor 的类型分开匹配:
  3. 对于 PointcutAdvisor 类型顾问,则需要匹配调用类和调用方法。
    • 进行类和方法的匹配,如果都匹配则认为 Advisor 适用于当前方法。
    • 随后通过 runtime 参数判断了当前拦截器是否是动态拦截器。
    • 如果是动态拦截器则封装成 InterceptorAndDynamicMethodMatcher类型保存到集合中。所谓的动态拦截器,即每次调用时都会判断一次是否可以执行增强。
    • 如果不是动态拦截器则直接添加到 拦截器集合中,随后将拦截器集合返回。
  4. 对于 IntroductionAdvisor 类型顾问,该类型是引介顾问,并不会精确到方法级别,所以对调用类进行校验,如果匹配则认为适用。
  5. 对于 IntroductionAdvisor 类型顾问,直接添加。

2. CglibMethodInvocation#proceed

CglibMethodInvocation#proceed 调用其父类方法 ReflectiveMethodInvocation#proceed,作用为 执行了过滤器链流程,其实现如下:

@Override
@Nullable
public Object proceed() throws Throwable {
        // We start with an index of -1 and increment early.
        // 如果所有拦截器执行结束,调用真正的方法
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
                return invokeJoinpoint();
        }
        // 获取下一个拦截器
        Object interceptorOrInterceptionAdvice =
                        this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        // 如果是动态拦截器
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
                // Evaluate dynamic method matcher here: static part will already have
                // been evaluated and found to match.
                InterceptorAndDynamicMethodMatcher dm =
                                (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
                Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
                // 判断调用是否匹配,如果匹配则调用拦截器方法
                if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
                        return dm.interceptor.invoke(this);
                }
                else {
                        // Dynamic matching failed.
                        // Skip this interceptor and invoke the next in the chain.
                        // 否则递归执行下一个拦截器
                        return proceed();
                }
        }
        else {
                // 非动态调用直接调用拦截器方法。
                return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
}

ProxyFactory#getInterceptorsAndDynamicInterceptionAdvice 返回的拦截器集合保存到了 interceptorsAndDynamicMethodMatchers 中, currentInterceptorIndex 记录执行到哪个拦截器。

其逻辑简述如下:

  1. 判断 this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1 是否成立,如果成立,则说明当前拦截器链已经执行结束,开始执行目标对象的目标放啊
  2. 否则从 interceptorsAndDynamicMethodMatchers 中获取下一个拦截器。
  3. 如果拦截器类型是 InterceptorAndDynamicMethodMatcher 则认为动态匹配,需要每次调用前调用 MethodMatcher#matches(java.lang.reflect.Method, java.lang.Class<?>, java.lang.Object...) 方法判断是否匹配,如果匹配则执行该拦截器,否则递归回到第一步找下一个拦截器。
  4. 如果拦截器类型不是 InterceptorAndDynamicMethodMatcher ,则直接执行该拦截器即可。

6.3.2 targetInterceptor

targetInterceptor 实现了 MethodInterceptor 接口,当方法没有适用拦截器和动态拦截建议 则可能使用该拦截器。aopInterceptor 在不同的情况下有不同的实现类,其规则如下:

org.springframework.aop.framework.CglibAopProxy#getCallbacks

// 如果需要暴露代理类,则需要在执行前将代理类保存到 AOP上下文 中,
// 而 StaticUnadvisedExposedInterceptor 和 DynamicUnadvisedExposedInterceptor 中完成了此操作。
if (exposeProxy) {
        targetInterceptor = (isStatic ?
                        // 如果是静态,直接将 getTarget 对象传入,因为对象不可变。否则传入 TargetSource 由拦截器在内部获取。
                        new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
                        new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
else {
        targetInterceptor = (isStatic ?
                        new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
                        new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}

即:

  1. 如果 exposeProxy = true && 代理类是静态StaticUnadvisedExposedInterceptor
        @Override
        @Nullable
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                Object oldProxy = null;
                try {
                        // 切换当前AOP上下文的 代理类对象
                        oldProxy = AopContext.setCurrentProxy(proxy);
                        Object retVal = methodProxy.invoke(this.target, args);
                        return processReturnType(proxy, this.target, method, retVal);
                }
                finally {
                        // 重置回上下文对象
                        AopContext.setCurrentProxy(oldProxy);
                }
        }
  1. 如果 exposeProxy = true && 代理类不是静态DynamicUnadvisedExposedInterceptor
        @Override
        @Nullable
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                Object oldProxy = null;
                Object target = this.targetSource.getTarget();
                try {
                        oldProxy = AopContext.setCurrentProxy(proxy);
                        Object retVal = methodProxy.invoke(target, args);
                        return processReturnType(proxy, target, method, retVal);
                }
                finally {
                        AopContext.setCurrentProxy(oldProxy);
                        if (target != null) {
                                this.targetSource.releaseTarget(target);
                        }
                }
        }
  1. 如果 exposeProxy = false && 代理类是静态StaticUnadvisedInterceptor
        @Override
        @Nullable
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                Object retVal = methodProxy.invoke(this.target, args);
                return processReturnType(proxy, this.target, method, retVal);
        }
  1. 如果 exposeProxy = false && 代理类不是静态DynamicUnadvisedInterceptor
        @Override
        @Nullable
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                Object target = this.targetSource.getTarget();
                try {
                        Object retVal = methodProxy.invoke(target, args);
                        return processReturnType(proxy, target, method, retVal);
                }
                finally {
                        if (target != null) {
                                this.targetSource.releaseTarget(target);
                        }
                }
        }

注: 这里的所说的静态是 根据 TargetSource#isStatic 方法判断,标志用户返回当前bean是否为静态的,比如常见的单例bean就是静态的,而原型模式下就是动态的。这里这个方法的主要作用是,对于静态的bean,spring是会对其进行缓存的,在多次使用TargetSource获取目标bean对象的时候,其获取的总是同一个对象,通过这种方式提高效率。

6.3.3 SerializableNoOp

SerializableNoOp 没有做任何事。用于无需代理或无法代理的方法。

public static class SerializableNoOp implements NoOp, Serializable {
}

6.3.4 StaticDispatcher

StaticDispatcher 是静态类情况下的懒加载策略,其实现如下:

private static class StaticDispatcher implements Dispatcher, Serializable {

        @Nullable
        private final Object target;

        public StaticDispatcher(@Nullable Object target) {
                this.target = target;
        }

        @Override
        @Nullable
        public Object loadObject() {
                return this.target;
        }
}

6.3.5 AdvisedDispatcher

AdvisedDispatcher 仍为懒加载策略。 调用时机为代理类调用的是 Advised 接口声明的方法时,其实现如下:

/**
 * Dispatcher for any methods declared on the Advised class.
 */
private static class AdvisedDispatcher implements Dispatcher, Serializable {

        private final AdvisedSupport advised;

        public AdvisedDispatcher(AdvisedSupport advised) {
                this.advised = advised;
        }

        @Override
        public Object loadObject() {
                return this.advised;
        }
}

6.3.6 EqualsInterceptor

EqualsInterceptor 用于处理 equals 方法的调用,其实现如下:

private static class EqualsInterceptor implements MethodInterceptor, Serializable {

        private final AdvisedSupport advised;

        public EqualsInterceptor(AdvisedSupport advised) {
                this.advised = advised;
        }

        @Override
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) {
                Object other = args[0];
                if (proxy == other) {
                        return true;
                }
                if (other instanceof Factory) {
                        Callback callback = ((Factory) other).getCallback(INVOKE_EQUALS);
                        if (!(callback instanceof EqualsInterceptor)) {
                                return false;
                        }
                        AdvisedSupport otherAdvised = ((EqualsInterceptor) callback).advised;
                        return AopProxyUtils.equalsInProxy(this.advised, otherAdvised);
                }
                else {
                        return false;
                }
        }
}

6.3.7 HashCodeInterceptor

HashCodeInterceptor用于处理 hashcode 方法的调用,其实现如下:

private static class HashCodeInterceptor implements MethodInterceptor, Serializable {

        private final AdvisedSupport advised;

        public HashCodeInterceptor(AdvisedSupport advised) {
                this.advised = advised;
        }

        @Override
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) {
                return CglibAopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode();
        }
}

6.4 总结

我们这里总结一下Spring Aop Cglib 的代理过程:

  1. Spring 服务启动后,会加载自动代理创建器 AbstractAutoProxyCreator。AbstractAutoProxyCreator有多个实现类,不过主体逻辑基本相同,这里就用 AbstractAutoProxyCreator 表述。
  2. 在 Spring Bean 创建过程中,AbstractAutoProxyCreator 会从容器中获取 Advisor 集合,并判断是否有适用于当前Bean 的Advisor 集合。如果存在,则调用 AbstractAutoProxyCreator#createProxy 准备开始创建该 Bean的 代理。
  3. 创建代理前会做一些准备工作,如:创建当前Bean对应的 ProxyFactory ,并将适用 的Advisor 赋值给 ProxyFactory 等。随后通过 ProxyFactory#getProxy(java.lang.ClassLoader) 创建代理对象。
  4. Spring Bean 代理的创建可以选择 Jdk动态代理和 Cglib 动态代理,本文分析 Cglib 过程,因此这里假定Bean 使用 Cglib 代理。所以这里选择 CglibAopProxy#getProxy(java.lang.ClassLoader) 创建代理对象
  5. 在 CglibAopProxy#getProxy(java.lang.ClassLoader) 在创建代理对象时会添加 Callback集合用于代理对象调用时的增强操作,并且会添加代理回调过滤器 ProxyCallbackFilter 来选择使用合适的 Callback 来操作 。
  6. 当代理对象调用某个方法时,会通过 ProxyCallbackFilter 来选择合适的Callback 执行。如常规的调用会执行 DynamicAdvisedInterceptor 。
  7. 在 DynamicAdvisedInterceptor 中会遍历当前 ProxyFactory 中的 Advisor 集合(这里的 Advisor集合就是第三步的准备工作中 保存到 ProxyFactory 中的),挑选出适合当前调用方法的 Advisor 依次执行,最后执行真正的方法。

7. Spring Aop总结

  1. @EnableAspectJAutoProxy开始Aop功能。实际上在引入aspectj包之后, Spring默认会通过AopAutoConfiguration配置类开启AOP功能

  2. @EnableAspectJAutoProxy 注解通过@Import(AspectJAutoProxyRegistrar.class)引入了AspectJAutoProxyRegistrar

  3. AspectJAutoProxyRegistrar中注册了自动代理创建器AnnotationAwareAspectJAutoProxyCreator。之后的操作都在AnnotationAwareAspectJAutoProxyCreator中进行。

  4. AnnotationAwareAspectJAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor接口, 所以会在Bean创建的时候,发现并记录了合适的所有的Advisor并进行拦截代理。

    • 4.1 发现所有的Advisor : 这里分为两步。

      • 第一步是扫描BeanFactory中的所有Advisor类型的bean。这里直接通过BeanFactory获取即可。假设这里获取到的Advisor集合为Advisors1。
      • 第二步则是通过扫描@Aspect注解找到切面类,随后筛选切面类中的方法。找到被@Around、@Before等注解修饰的通知(Advice) 进行解析,并封装成不同的Advice类型(这里不包括@Pointcut注解的解析), @Pointcut会被解析成切入点(Pointcut类)。随后Advice和Pointcut会被一起封装成一个Advisor (顾问,也即是Advisor) 。也就是说,在这里Spring封装出了Pointcut类(实际上是AspectJExpressionPointcut)和Advice类(这里的Advice根据注解使用的不同分为多个种类,如AspectJAroundAdvice、AspectJMethodBeforeAdvice等)以及包含他俩的Advisor(实际上是InstantiationModelAwarePointcutAdvisorImpl)。这个过程是在ReflectiveAspectJAdvisorFactory#getAdvisor和InstantiationModelAwarePointcutAdvisorImpl构造函数中完成的。这里就动态解析出了@Aspect 注解下的切入点,并被封装成了Advisor集合。假设这里的Advisor集合为Advisors2。
      • 这两步结束后,就解析出来了当前所有的Advisors =Advisors1 + Advisors2;

      注:可以简单的理解为一个Advisor即一个增强操作,一个Advisor包含Advice和Pointcut。 Advice定义了具体增强操作,如前置,后置,环绕等, Pointcut定义了织入规则(即哪些类可以被代理),满足规则的bean方法才能被增强。

    • 4.2. 筛选所有合适的Advisor:上一-步筛选出来的Advisor可能并不适用于当前bean,所以需要筛选出合适于当前bean的Advisor。比如@Pointcut ("execution (* com.demo.service.impl.UserServiceImpl.findAll())");切入的是UserServiceImpl,而当前的bean如果是RoleServiceImpl就不应该被此Advisor所增强。

  5. 第四步结束后,这里已经筛选出来了适合当前bean所使用的Advisor,下面需要创建代理类。创建代理则是委托给了ProxyFactory来完成。

    • ProxyFactory 使用 Advisor 中的 Advice 创建出来了代理增强类并注入到Spring容器中。

    • ProxyFactory中有筛选出来的Advisor集合,即Advisors

    • ProxyFactory根据情况选择Jdk代理(JdkDynamicAopProxy)或者Cglib代理(ObjenesisCglibAopProxy)来完成创建代理类的操作。

    • 最终执行的代理方法,实际上都是MethodInterceptor#invoke方法。

    这里需要注意的是:对于AspectJAroundAdvice、AspectJAfterThrowingAdvice他们直接实现了MethodInterceptor接口,所以可以直接使用,但是对于AspectJMethodBeforeAdvice、AspectJAfterAdvice、AspectJAfterReturningAdvice则需要进行一个适配。这个适配的是在创建代理类的过程中。在AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice方法中完成。

7.1 @EnableAspectJAutoProxy注解

@EnableAspectJAutoProxy 注解通过@Import(AspectJAutoProxyRegistrar.class)引入了AspectJAutoProxyRegistrar类,实现了SmartInstantiationAwareBeanPostProcessor接口, 所以会在Bean创建的时候,发现并记录了合适的所有的Advisor并进行拦截代理。

image.png

7.2 registerBeanPostProcessors(beanFactory)

注册bean的后置处理器。

image.png

7.3 finishBeanFactoryInitialization(beanFactory);

完成其他bean的注册。

image.png

7.4 代理执行目标方法

image.png

7.5 AOP 的执行顺序

try{
    前置通知@Before
    目标方法的执行
    返回通知@AfterReturning
 }catch(){
     异常通知@AfterThrowing
 }finally{
     后置通知 @After
 }
  • 正常:前置通知===目标方法===返回通知===后置通知
  • 异常: 前置通知===目标方法===异常通知===后置通知

环绕通知的执行顺序

@Around("execution(* com.hsf.spring.aop.HelloService.sayHello(..))")
public void around(ProceedingJoinPoint joinPoint) {
   try {
      System.out.println("【环绕前置通知】 around before");
      joinPoint.proceed();    // 放行切点的方法,不放行则会阻塞调用
      System.out.println("【环绕返回通知】around after");
   } catch (Throwable throwable) {
      throwable.printStackTrace();
      System.out.println("【环绕异常通知】 around throwable");
   }finally {
      System.out.println("【环绕后置通知】 around throwable");
   }

}
  • 正常情况:环绕前置=====目标方法执行=====环绕返回=====环绕后置通知
  • 异常情况:环绕前置=====目标方法执行=====环绕异常=====环绕后置通知

8. Spring扩展功能分析方法

8.1 AOP给容器中添加了什么组件

AbstractBeanDefinition的构造器打断点,就能知道容器中的bean定义信息,Spring也可能在底层直接new对象注册进去。最好给refresh()十二大步的最后一步打上断点,在debug控制台看有哪些没见过的组件。单独分析他们即可

每一个功能的开启,要么写配置,要么注解。@EnableXXX 开启 xxx功能的注解。这个注解很重要。

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy { }
  • 给容器中注册AspectJAutoProxyRegistrar(实现了ImportBeanDefinitionRegistrar);

  • 给容器中导入了 AnnotationAwareAspectJAutoProxyCreator

8.2 这个组件做了什么功能(AnnotationAwareAspectJAutoProxyCreator)

它是BeanPostProcessor

  • 追踪getBean的整个流程,看什么时候 AnnotationAwareAspectJAutoProxyCreator 执行

  • AnnotationAwareAspectJAutoProxyCreator 直接打断点

AnnotationAwareAspectJAutoProxyCreator 第一次运行的时候分析组装好了切面、增强器(通知方法)的所有信息;

参考文章

Spring5源码注释github地址
Spring源码深度解析(第2版)
spring源码解析
Spring源码深度解析笔记
Spring注解与源码分析
Spring注解驱动开发B站教程