Spring源码之AOP

Spring源码之AOP

AOP是Aspect-Oriented Programming,面向切面编程

1. 概述

Advice通知

Adivce定义在连接点做什么,为切面增强提供织入接口,主要描述Spring AOP围绕方法调用而诸如的切面行为

Pointcut切点

Pointcut决定Advice通知应该作用于哪个连接点,也就是说Pointcut来定义需要增强的方法的集

Advisor通知器

通过Advisor,可以定义应该使用哪个通知并会在哪个关注点使用它,也就是通过Advisor,把Advice和Pointcut结合起来,这个结合为使用IoC容器配置AOP应用

2. 设计原理

Spring的AOP模块中,一个主要的部分是代理对象的生成,对于Spring应用,是通过配置和调用Spring的ProxyFactoryBean来完成这个任务。在ProxyFactoryBean中,封装了主要代理对象的生成过程,在这个生成过程中,可以使用JDK的Proxy和CGLIB这两种生成方式

以ProxyFactory的设计为中心可以看到其继承关系图:

  • 作为共同基类ProxyConfig可以看成是一个数据基类,这个数据基类为ProxyFactoryBean这样的子类提供了配置属性
  • 在另外一个基类AdvisedSupport中,封装了AOP对通知和通知器的相关操作,这些操作对于不同的AOP的代理对象的生成都是一样的,但对于具体的AOP代理对象和的创建,AdvisedSupport吧它交给它的子类去完成
  • 对于ProxyCreatorSupport,可以将它看成是其子类创建AOP代理对象的一个辅助类

通过继承以上的基类的功能实现,具体的AOP代理对象的生成,根据不同的需要,分别由ProxyFactoryBean、AspectJProxyFactory和ProxyFactory来完成。对于需要使用AspectJ的AOP应用,AspectProxyFactory起到集成Spring和AspectJ的作用;对于使用Spring AOP的应用,ProxyFactoryBean和ProxyFactory都提供了AOP功能的封装,只是使用ProxyFactoryBean,可以再IoC容器中完成声明式配置,而使用ProxyFactory,则需要编程式地使用Spring AOP的功能

3. ProxyFactoryBean生成AopProxy代理对象

在Spring AOP的使用中,可以通过ProxyFactoryBean来配置目标对象和切面行为,这个ProxyFactoryBean是一个FactoryBean(在之前IoC有对此分析过)

ProxyFactoryBean的AOP实现需要依赖JDK或者CGLIB提供的Proxy特性。从FactoryBean中获取对象,是以getObject()方法作为入口完成的;ProxyFactoryBean实现中的getObject方法,是FactoryBean需要实现的接口。对ProxyFactoryBean来说,把需要对target的目标对象增加的增强处理,都通过getObject方法进行封装了,这些增强处理是为AOP功能的实现提供服务的。

如下图,getObject方法首先对通知器链进行初始化,通知器链封装了一系列的拦截器,这些拦截器都要从配置中读取,然后为代理对象的生成做好准备,在生成代理对象时,因为Spring中有singleton类型和prototype类型这两种不同的bean,所以要对代理对象生成一个区分

//org.springframework.aop.framework.ProxyFactoryBean    
public Object getObject() throws BeansException {
        //初始化通知链
        initializeAdvisorChain();
        //对singleton类型和prototype类型这两种不同的bean,对代理对象生成一个区分
        if (isSingleton()) {
            return getSingletonInstance();
        }
        else {
            if (this.targetName == null) {
                logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
                        "Enable prototype proxies by setting the 'targetName' property.");
            }
            return newPrototypeInstance();
        }
    }

为Proxy代理对象配置Advisor链是在initializeAdvisorChain方法中完成的,初始化过程中有一个标志位advisorChainInitialized,用来表示通知器链是否已经初始化,所以初始化是发生在应用第一次通过ProxyFactoryBean获取代理对象的时候。完成初始化后,接着会读取配置中出现的所有通知器(getBean方法获取),然后把读取的通知器加入到拦截链中。

//org.springframework.aop.framework.ProxyFactoryBean
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
        if (this.advisorChainInitialized) {
            return;
        }

        if (!ObjectUtils.isEmpty(this.interceptorNames)) {
            if (this.beanFactory == null) {
                throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
                        "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
            }

            // Globals can't be last unless we specified a targetSource using the property...
            if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
                    this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
                throw new AopConfigException("Target required after globals");
            }

            // 这里是添加Advisor链的调用,是通过interceptorNames属性进行配置的
            for (String name : this.interceptorNames) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Configuring advisor or advice '" + name + "'");
                }

                if (name.endsWith(GLOBAL_SUFFIX)) {
                    if (!(this.beanFactory instanceof ListableBeanFactory)) {
                        throw new AopConfigException(
                                "Can only use global advisors or interceptors with a ListableBeanFactory");
                    }
                    addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
                            name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
                }

                else {
                    // 如果程序在这里被调用,那么需要加入命名的拦截器,并且检查该类型是
                    // singleton 还是 prototype.
                    Object advice;
                    if (this.singleton || this.beanFactory.isSingleton(name)) {
                        // Add the real Advisor/Advice to the chain.
                        advice = this.beanFactory.getBean(name);
                    }
                    else {
                        // It's a prototype Advice or Advisor: replace with a prototype.
                        // Avoid unnecessary creation of prototype bean just for advisor chain initialization.
                        advice = new PrototypePlaceholderAdvisor(name);
                    }
                    addAdvisorOnChainCreation(advice, name);
                }
            }
        }

        this.advisorChainInitialized = true;
    }

生成singleton的代理对象在getSingletonInstance()代码中完成,这个方法是ProxyFactoryBean生成AopProxy代理对象的调用入口。代理对象会封装对target目标对象的调用,也就是说针对target对象的方法调用行为会被这里生成的对象所拦截。具体的生成过程是,首先读取ProxyFactoryBean中的配置,为生成代理对象做好必要的准备,比如设置代理的方法调用接口等。Spring通过AopProxy类来具体生成代理对象

//org.springframework.aop.framework.ProxyFactoryBean    
private synchronized Object getSingletonInstance() {
        if (this.singletonInstance == null) {
            this.targetSource = freshTargetSource();
            if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
                // 根据AOP框架来判断需要代理的接口
                Class<?> targetClass = getTargetClass();
                if (targetClass == null) {
                    throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
                }
                //设置代理对象的接口
                setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
            }
            // Initialize the shared singleton instance.
            super.setFrozen(this.freezeProxy);
            this.singletonInstance = getProxy(createAopProxy());
        }
        return this.singletonInstance;
    }

//通过createAopProxy返回的AopProxy返回的AopProxy来得到代理对象
protected Object getProxy(AopProxy aopProxy) {
        return aopProxy.getProxy(this.proxyClassLoader);
}

上述出现了AopProxy类型的对象,Spring利用这个接口类把AOP代理对象的实现与框架的其他部分有效地分离开来。AopProxy是一个接口,它由两个子类实现,一个是CglibAopProxy,一个是JdkDynamicAopProxy,分别是通过CGLIB(对象)和JDK(接口)来生成代理对象

//org.springframework.aop.framework.ProxyCreatorSupport
protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        //通过AopProxyFactory取得AopProxy,这个AopProxyFactory是在初始化函数中定义的,
        //使用的是DefaultAopProxyFactory
        return getAopProxyFactory().createAopProxy(this);
    }

具体代理类的生成是在ProxyFactoryBean的基类ProxyCreatorSupport借助AopProxyFactory完成的,因为ProxyFactoryBean本身就是AdvisedSupport的子类,所以在ProxyFactoryBean获得AopProxy是很方便的。需要的代理对象的信息都封装在AdvisedSupport里,这个也是生成AopProxy的方法的输入参数,这里设置为this,因为ProxyCreatorSupport本身就是AdvisedSupport的子类

同时,这里使用的AopProxyFactory是DefaultAopProxyFactory,作为AopProxy的创建工厂对象,可以根据不同的需要生成这两种AopProxy对象:JDK(通过接口),CGLIB(通过对象)

//org.springframework.aop.framework.DefaultAopProxyFactory
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
            //如果是接口类,使用JDK来生成Proxy
            if (targetClass.isInterface()) {
                return new JdkDynamicAopProxy(config);
            }//如果不是接口类,那么使用CGLIB来生成
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

先看看JdkDynamicAopProxy使用JDK的Proxy类来生成代理对象

//org.springframework.aop.framework.JdkDynamicAopProxy
public Object getProxy(ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
        }
        //需要先从advised对象中取得代理对象的代理接口配置
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        /*
          调用newProxyInstance方法,得到Proxy代理对象,指定三个参数:类装载器、代理接口、Proxy回调方法
          所在的对象,这个对象需要实现IanInvocationHandler接口(定义了invoke方法),这个invoke方法就          是Proxy代理对象的回调方法,完成了AOP编织实现的封装。
        */
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

再看看CGLIB生成AopProxy代理对象

//org.springframework.aop.framework.CglibAopProxy   
public Object getProxy(ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
        }
        //从advised中取得IoC容器中配置的target对象
        try {
            Class<?> rootClass = this.advised.getTargetClass();
            Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

            Class<?> proxySuperClass = rootClass;
            if (ClassUtils.isCglibProxyClass(rootClass)) {
                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);

            // 创建并配置CGLIB的Enhancer,这个Enhancer对象是CGLIB的主要操作类
            Enhancer enhancer = createEnhancer();
            if (classLoader != null) {
                enhancer.setClassLoader(classLoader);
                if (classLoader instanceof SmartClassLoader &&
                        ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                    enhancer.setUseCache(false);
                }
            }
            //设置Enhancer独享,包括代理接口,回调方法
            enhancer.setSuperclass(proxySuperClass);
            enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
            enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
            enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
            //实际上是通过设置DynamicAdvisedInterceptor拦截器来完成AOP功能的
            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
            enhancer.setCallbackFilter(new ProxyCallbackFilter(
                    this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
            enhancer.setCallbackTypes(types);

            // 生成代理类并返回
            return createProxyClassAndInstance(enhancer, callbacks);
        }
        catch (CodeGenerationException ex) {
            throw new AopConfigException("Could not generate CGLIB subclass of class [" +
                    this.advised.getTargetClass() + "]: " +
                    "Common causes of this problem include using a final class or a non-visible class",
                    ex);
        }
        catch (IllegalArgumentException ex) {
            throw new AopConfigException("Could not generate CGLIB subclass of class [" +
                    this.advised.getTargetClass() + "]: " +
                    "Common causes of this problem include using a final class or a non-visible class",
                    ex);
        }
        catch (Exception ex) {
            // TargetSource.getTarget() failed
            throw new AopConfigException("Unexpected AOP exception", ex);
        }
    }

这样,通过AopProxy对象封装target目标对象之后,ProxyFactoryBean的getObject方法的到的对象就不是一个普通的Java对象了,而是一个AopProxy代理对象

4. Spring AOP拦截器调用的实现

4.1 JdkDynamicAopProxy的invoke拦截

在JdkDynamicAopProxy中生成Proxy对象

Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)

这里的this参数对应的就是InvocationHandler对象,InvocationHandler是JDK定义的反射类的一个接口,这个接口定义了invoke方法,作为JDK Proxy代理对象进行拦截的回调入口出现的,从而通过invoke的具体实现来完成对目标对象方法调用的拦截或者说功能加强的工作。

JdkDynamicAopProxy中的invoke方法如下:

  • 对Proxy对象的代理设置是在invoke方法中完成的,这些设置包括获取目标对象、拦截器链,同时把这些对象作为输入创建了ReflectiveMethodInvocation对象,通过这个对象来完成对AOP功能实现的封装
  • invoke方法包含了一个完整的拦截器链对目标对象的拦截过程
//org.springframework.aop.framework.JdkDynamicAopProxy  
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MethodInvocation invocation;
        Object oldProxy = null;
        boolean setProxyContext = false;

        TargetSource targetSource = this.advised.targetSource;
        Class<?> targetClass = null;
        Object target = null;

        try {
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                // 如果目标对象没有实现Object类的基本方法:equals
                return equals(args[0]);
            }
            if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                // 如果目标对象没有实现Object类的基本方法:hashCode
                return hashCode();
            }
            if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                    method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                // 根据代理对象的配置来调用服务
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }

            Object retVal;

            if (this.advised.exposeProxy) {
                // Make invocation available if necessary.
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }

            // 得到目标对象的地方
            target = targetSource.getTarget();
            if (target != null) {
                targetClass = target.getClass();
            }

            // 获得定义好的拦截器链
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            // 如果没有设定拦截器,那么直接调用target的对应方法
            if (chain.isEmpty()) {
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
            }
            else {
                // 如果有拦截器的设定,那么需要调用拦截器之后才调用目标独享的相应方法
                 // 通过构造一个ReflectiveMethodInvocation来实现
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // 沿着拦截器链继续前进.
                retVal = invocation.proceed();
            }

            // Massage return value if necessary.
            Class<?> returnType = method.getReturnType();
            if (retVal != null && retVal == target && 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);
            }
        }
    }

4.2 CglibAopProxy的intercept拦截

CglibAopProxy实现拦截调用是在DynamicAdvisedInterceptor对象中实现的,这个回调的实现在intercept中完成,和JdkDynamicAopProxy类似,CglibAopProxy中通过构造CglibMethodInvocation对象来完成拦截器链的调用,而JdkDynamicAopProxy是通过构造ReflectiveMethodInvocation来实现这个功能

//org.springframework.aop.framework.CglibAopProxy的内部类-->DynamicAdvisedInterceptor   
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            Object oldProxy = null;
            boolean setProxyContext = false;
            Class<?> targetClass = null;
            Object target = null;
            try {
                if (this.advised.exposeProxy) {
                    // Make invocation available if necessary.
                    oldProxy = AopContext.setCurrentProxy(proxy);
                    setProxyContext = true;
                }
                // May be null. Get as late as possible to minimize the time we
                // "own" the target, in case it comes from a pool...
                target = getTarget();
                if (target != null) {
                    targetClass = target.getClass();
                }
                 //从advised中获取配置好的AOP通知
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                Object retVal;
                // 如果没有通知则直接调用target对象的调用方法.
                if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                    retVal = methodProxy.invoke(target, args);
                }
                else {
                    // 通过CglibMethodInvocation来启动advice通知
                    retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
                }
                retVal = processReturnType(proxy, target, method, retVal);
                return retVal;
            }
            finally {
                if (target != null) {
                    releaseTarget(target);
                }
                if (setProxyContext) {
                    // Restore old proxy.
                    AopContext.setCurrentProxy(oldProxy);
                }
            }
    }

4.3 目标方法的调用

如果没有设置拦截器,那么会对目标对象的方法直接进行调用,JdkDynamicAopProxy是通过AopUtils使用反射机制在其invokeJoinpointUsingReflection方法中实现

//org.springframework.aop.support.AopUtils
public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
            throws Throwable {

        // 反射调用方法
        try {
            ReflectionUtils.makeAccessible(method);
            return method.invoke(target, args);
        }
        catch (InvocationTargetException ex) {
            // Invoked method threw a checked exception.
            // We must rethrow it. The client won't see the interceptor.
            throw ex.getTargetException();
        }
        catch (IllegalArgumentException ex) {
            throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
                    method + "] on target [" + target + "]", ex);
        }
        catch (IllegalAccessException ex) {
            throw new AopInvocationException("Could not access method [" + method + "]", ex);
        }
    }

对于CglibAopProxy,对目标对象的调用时通过MethodProxy对象直接调用的

retVal = methodProxy.invoke(target, args);

形式上相对JdkDynamicAopProxy较为简单,但实现的功能都是一样的

4.4 AOP拦截器链的调用

以JdkDynamicAopProxy为例,对拦截器链的调用是在ReflectiveMethodInvocation的proceed方法中实现的,这个方法会逐个运行拦截器的拦截方法,在此之前需要对代理方法完成一个匹配判断(match),来决定是否需要实行通知增强

//org.springframework.aop.framework.ReflectiveMethodInvocation  
public Object proceed() throws Throwable {
        //  从索引为-1的拦截器开始调用,并按序递增
        // 如果拦截器链中的拦截器迭代调用完毕,则开始调用target函数
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }
        //这里是沿着定义好的interceptorOrInterceptionAdvice链进行处理
        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // 这里对拦截器进行动态匹配判断,如果和定义的Pointcut匹配,则这个advice会得到执行
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
                return dm.interceptor.invoke(this);
            }
            else {
                // 如果不匹配,则proceed会被递归调用,直到所有拦截器都被允许过位置
                return proceed();
            }
        }
        else {
            // 如果是一个interceptor,直接调用这个interceptor对应的方法
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

4.5 配置通知器

//org.springframework.aop.framework.ReflectiveMethodInvocation
Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

这个interceptorOrInterceptionAdvice是获得的拦截器,通过拦截器机制对目标对象行为增强其作用。他是interceptorsAndDynamicMethodMatchers持有的List中的一个元素。

在之前的invoke方法中,可以看到List中的interceptors是在哪个调用中获取的

//org.springframework.aop.framework.JdkDynamicAopProxy
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

可以看出,获取interceptors的操作是由advised对象完成的,这个advised是一个AdvisedSupport对象,具体代码如下:

//org.springframework.aop.framework.AdvisedSupport
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
        /*
        这里使用了cache,利用cache去获取已有的interceptor链,但是第一次还是需要自己动手生成
        这个interceptor链的生成是由advisorChainFactory完成的,这里使用的是                                DefaultadvisorChainFactory
        */
        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;
    }

取得拦截器链的工作是由配置好的advisorChainFactory完成的,此处advisorChainFactory被配置成一个DefaultadvisorChainFactory对象,在DefaultadvisorChainFactory中实现了interceptor链的获取过程

DefaultadvisorChainFactory会通过一个AdvisorAdapterRegistry来实现拦截器的注册,AdvisorAdapterRegistry对advice的织入功能起了很大的作用,有了AdvisorAdapterRegistry注册器,利用它来对ProxyFactoryBean配置中得到的通知进行适配,从而获得相应的拦截器,再把它加入前面设置好的List中,完成所谓的拦截器注册过程。完成以后,List中的拦截器会被JDK生成的AopProxy代理对象的invokle方法或者CGLIB对象的intercept拦截方法获得,并启动拦截器的invoke调用,最终触发通知的切面增强

//org.springframework.aop.framework.DefaultAdvisorChainFactory]
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
            Advised config, Method method, Class<?> targetClass) {

        // 长度由配置的通知器的个数来决定,即XML中对ProxyFactoryBean做的interceptorNames属性配置
        List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
        Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
        boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

        for (Advisor advisor : config.getAdvisors()) {
            if (advisor instanceof PointcutAdvisor) {
                // 拦截器链是通过AdvisorAdapterRegistry来加入的,对advice的织入起了很大的作用.
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    //使用MethodMatchers的matches方法进行匹配判断
                    if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
                        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) {
                                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;
    }

//判断Advisors是否符合配置要求    
private static boolean hasMatchingIntroductions(Advised config, Class<?> actualClass) {
        for (int i = 0; i < config.getAdvisors().length; i++) {
            Advisor advisor = config.getAdvisors()[i];
            if (advisor instanceof IntroductionAdvisor) {
                IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
                if (ia.getClassFilter().matches(actualClass)) {
                    return true;
                }
            }
        }
        return false;
    }

}

实际上这里的advisor通知器是从AdvisorSupport中取得的。在ProxyFactoryBean 的getObject方法中对advisor进行初始化时就从XML配置中获取了advisor通知器

//org.springframework.aop.framework.ProxyFactoryBean
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
        if (this.advisorChainInitialized) {
            return;
        }

        if (!ObjectUtils.isEmpty(this.interceptorNames)) {
            if (this.beanFactory == null) {
                throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
                        "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
            }

            // Globals can't be last unless we specified a targetSource using the property...
            if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
                    this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
                throw new AopConfigException("Target required after globals");
            }

            // Materialize interceptor chain from bean names.
            for (String name : this.interceptorNames) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Configuring advisor or advice '" + name + "'");
                }

                if (name.endsWith(GLOBAL_SUFFIX)) {
                    if (!(this.beanFactory instanceof ListableBeanFactory)) {
                        throw new AopConfigException(
                                "Can only use global advisors or interceptors with a ListableBeanFactory");
                    }
                    addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
                            name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
                }

                else {
                    // 需要对Bean类型进判断,是单例还是prototype.
                    Object advice;
                    if (this.singleton || this.beanFactory.isSingleton(name)) {
                        // 这里是取得advisor的地方,通过BeanFactory取得的,吧interceptorNames这个
                        //List中的interceptor名字交给BeanFactory,然后调用BeanFactory的getBean方法
                        advice = this.beanFactory.getBean(name);
                    }
                    else {
                        // It's a prototype Advice or Advisor: replace with a prototype.
                        // Avoid unnecessary creation of prototype bean just for advisor chain initialization.
                        advice = new PrototypePlaceholderAdvisor(name);
                    }
                    addAdvisorOnChainCreation(advice, name);
                }
            }
        }

        this.advisorChainInitialized = true;
    }

advisor通知器的取得是委托给IoC容器完成的,但是在ProxyFactoryBean中是如何获取到IoC容器的?

public class ProxyFactoryBean extends ProxyCreatorSupport
        implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware {}

可以看出,ProxyFactoryBean实现了BeanFactoryAware接口,该接口可以实现把IoC容器设置到Bean自身定义一的一个树形中区,这样在这个Bean自身实现中就可以得到它所在的IoC容易从而调用getBean方法

4.6 Advice通知的实现

在为AopProxy代理对象配置拦截器的实现中,有一个取得拦截器的配置过程,这个过程是由DefaultAdvisorChainFactory实现的,这个工厂类负责生成拦截器链,在它的getInterceptorsAndDynamicInterceptionAdvice方法中,有一个适配和注册过程,在这个适配和注册过程中,通过配置Spring预先设计好的拦击诶,Spring加入了它对AOP实现的处理

  • 首先构造了一个AdvisorAdapterRegistry,通过GlobalAdvisorAdapterRegistry来返回默认的AdvisorAdapterRegistry,既是DefaultAdvisorAdapterRegistry
  • 然后对配置的Advisor通知器逐个遍历,这些通知器都是配置在interceptorNames中的
  • 从getInterceptorsAndDynamicInterceptionAdvice传递进来的advised参数对象中可以方便取得配置的通知器
  • 由DefaultAdvisorAdapterRegistry来完成拦截器的适配和注册过程
//org.springframework.aop.framework.DefaultAdvisorChainFactory
//getInterceptorsAndDynamicInterceptionAdvice方法

//得到注册器 GlobalAdvisorAdapterRegistry 是一个单例  
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

        for (Advisor advisor : config.getAdvisors()) {
            if (advisor instanceof PointcutAdvisor) {
                // Add it conditionally.
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                    //从DefaultAdvisorAdapterRegistry中取得MethodInterceptor的实现
                    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
                        if (mm.isRuntime()) {
                            // 在getInterceptors()方法中创建新的对象实例
                            for (MethodInterceptor interceptor : interceptors) {
                                interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                            }
                        }
                        else {
                            interceptorList.addAll(Arrays.asList(interceptors));
                        }
                    }
                }
            }

上述DefaultAdvisorAdapterRegistry的getInterceptors方法封装着advice织入实现,先看一下GlobalAdvisorAdapterRegistry是如何返回DefaultAdvisorAdapterRegistry的

//org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry
public abstract class GlobalAdvisorAdapterRegistry {

    private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();
    //单例,返回默认的实例DefaultAdvisorAdapterRegistry
    public static AdvisorAdapterRegistry getInstance() {
        return instance;
    }
    static void reset() {
        instance = new DefaultAdvisorAdapterRegistry();
    }
}

再看DefaultAdvisorAdapterRegistry的实现

  • 设置了一系列的adapter适配器,为AOP的advice提供编织能力
  • adapter的具体使用
    • 调用adapter的support方法,通过这个而方法来判断取得的advice属于什么类型的advice通知,从而根据不同的advice类型来注册不同的AdviceInterceptor,也就是拦截器
    • 这些AdviceInterceptor都是Spring AOP框架设计好了的,是为实现不同的advice功能提供服务的,实现了advice通知在AopProxy代理对象中的织入功能
//org.springframework.aop.framework.adapter.DefaultAdvisorAdapterRegistry

public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

    //持有一个AdvisorAdapter的List,这个List中的Adapter是与实现Spring AOP的advice增强功能相对应的
    private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);


    /*
      这里把已有的advice实现的Adapter加入进来,有非常熟悉的MethodBeforeAdvice、                        AfterReturningAdvice、ThrowsAdvice这些AOP的advice封装实现
     */
    public DefaultAdvisorAdapterRegistry() {
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }


    @Override
    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
        if (adviceObject instanceof Advisor) {
            return (Advisor) adviceObject;
        }
        if (!(adviceObject instanceof Advice)) {
            throw new UnknownAdviceTypeException(adviceObject);
        }
        Advice advice = (Advice) adviceObject;
        if (advice instanceof MethodInterceptor) {
            // So well-known it doesn't even need an adapter.
            return new DefaultPointcutAdvisor(advice);
        }
        for (AdvisorAdapter adapter : this.adapters) {
            // Check that it is supported.
            if (adapter.supportsAdvice(advice)) {
                return new DefaultPointcutAdvisor(advice);
            }
        }
        throw new UnknownAdviceTypeException(advice);
    }

    //这里是在DefaultAdvisorChainFactory中启动的getInterceptors方法
    @Override
    public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
        List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
        //从Advisor通知器配置中取得advice通知
        Advice advice = advisor.getAdvice();
        //如果通知是MethodInterceptor,直接加入interceptors的list,不需要适配
        if (advice instanceof MethodInterceptor) {
            interceptors.add((MethodInterceptor) advice);
        }
        /*
        对通知进行适配,使用已经配置好的Adapter:MethodBeforeAdviceAdapter、                          AfterReturningAdviceAdapter以及ThrowsAdviceAdapter,然后对应的adapter中封装好Aop
        编织功能的拦截器
        */
        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[interceptors.size()]);
    }

    @Override
    public void registerAdvisorAdapter(AdvisorAdapter adapter) {
        this.adapters.add(adapter);
    }

}

上述的getInterceptor调用中,从MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter、ThrowsAdviceAdapter这借个通知适配器的名字上可以看到,他们完全和advice一一对应,可将相应的advisor转换为interceptor,以MethodBeforeAdviceAdapter为例,它实现了AdviceAdapter的两个接口方法:

  • 一个是supportsAdvice,对advice的类型进行判断,如果是MethodBeforeAdvice则返回true
  • 另一个是对getInterceptor接口方法的实现,这个方法把advice通知器中取出,然后创建一个MethodBeforeAdviceInterceptor对象,通过这个对象把取得的advice通知包装起来并返回
//org.springframework.aop.framework.adapter.MethodBeforeAdviceAdapter
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

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

    @Override
    public MethodInterceptor getInterceptor(Advisor advisor) {
        MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
        return new MethodBeforeAdviceInterceptor(advice);
    }

}

到这里Spring AOP就实现了advice的织入,接着可以从MethodBeforeAdviceInterceptor中看看其对advice的封装以及invoke回调,首先可以看到触发了advice的before回调,然后才是MethodInvocation的proceed方法的调用。

//org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

    private MethodBeforeAdvice advice;


    /**
     * 为指定的Advice创建对应的MethodBeforeAdviceInterceptor对象
     */
    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }

   //这个invoke方法是拦截器的回调方法,会在代理对象的方法被调用时触发回调
    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
        return mi.proceed();
    }

}

了解了MethodBeforeAdviceInterceptor的实现原理之后,对于其他的advice通知的处理也是类似的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值