美文网首页
spring aop学习总结

spring aop学习总结

作者: 铁甲依然在_978f | 来源:发表于2018-01-23 10:22 被阅读0次

    AOP概述

    1. AOP定义概念


      这里写图片描述

      这里我们只要关注三个重点的概念:
      1)基础(base):目标对象
      2)切面(aspect):通知、增强目标对象的应用
      3)配置(configuration):编织(将目标对象和切面结合起来)

    2. Pointcut切点

    我们来看一下对于MethodMatcher对象和matches方法的API说明
    MethodMatcher:Checks whether the target method is eligible for advice.A MethodMatcher may be evaluated statically or at runtime (dynamically).Static matching involves method and (possibly) method attributes. Dynamic matching also makes arguments for a particular call available, and any effects of running
    previous advice applying to the joinpoint.
    检查目标方法是否与切面匹配,动态和静态匹配都包含了方法和方法参数信息来与切面进行匹配。
    matches:Perform static checking whether the given method matches.
    校验目标方法是否匹配的具体执行方法,返回boolean值

    1. Advisor通知器
      用来将切面和目标对象结合起来,完成这个作用的就是Advisor通知器。
    public class DefaultPointcutAdvisor extends AbstractGenericPointcutAdvisor implements Serializable {
    
        private Pointcut pointcut = Pointcut.TRUE;
    
        public DefaultPointcutAdvisor() {
        }
    
        //匹配所有方法(任务方法都会被此通知的切面拦截)
        public DefaultPointcutAdvisor(Advice advice) {
            this(Pointcut.TRUE, advice);
        }
    
        public DefaultPointcutAdvisor(Pointcut pointcut, Advice advice) {
            this.pointcut = pointcut;
            setAdvice(advice);
        }
    
        //设置目标对象
        public void setPointcut(Pointcut pointcut) {
            this.pointcut = (pointcut != null ? pointcut : Pointcut.TRUE);
        }
    
        @Override
        public Pointcut getPointcut() {
            return this.pointcut;
        }
    
        @Override
        public String toString() {
            return getClass().getName() + ": pointcut [" + getPointcut() + "]; advice [" + getAdvice() + "]";
        }
    
    }
    

    DefaultPointcutAdvisor是通知接口Advisor接口的一个实现,有两个属性,分别是advice和pointcut,用来分配配置Advice和Pointcut。

    AopProxy代理对象

    1. 设计原理
      AOP是通过配置和调用spring的ProxyFactoryBean来完成。ProxyFactoryBean封装了代理对象的生成过程。

    大致类图:


    1. ProxyFactoryBean配置
    <bean id="testAdvisor" class="com.TestAdvisor"/>
    <bean id="testAop" class="org.springframework.aop.framework.ProxyFactoryBean"
            p:proxyInterfaces="targetInterfaces"
            p:interceptorNames="testAdvisor"
            p:target-ref="target"/>
    
    • target:代理的目标对象

    • proxyInterfaces:代理所需要实现的接口,可以多个接口。该属性还有一个别名是Interfaces

    • interceptorNames:需要植入目标对象的bean列表。采用bean的名称指定。这些bean必须实现类 org.aopalliance.intercept.MethodInterceptor 或 org.springframework.aop.Advisor的bean ,配置中的顺序对应调用的顺序。

    • proxyTargetClass:是否对类进行代理(而不是进行对接口进行代理),设置为true时,使用CGLib代理,且proxyInterfaces属性被ProxyFactoryBean忽略。

      1. ProxyFactoryBean生成AopProxy代理对象
        ProxyFactoryBean生成代理对象以getObject方法作为入口。


        这里写图片描述

    我们来看下通知器配置链的初始化过程(ProxyFactoryBean.initializeAdvisorChain方法)

    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 + "'");
                    }
    
                    //若interceptorNames配置成aaa*,则获取所有aaa开头的advisor
                    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 {
                        // If we get here, we need to add a named interceptor.
                        // We must check if it's a singleton or prototype.
                        Object advice;
                        if (this.singleton || this.beanFactory.isSingleton(name)) {
                            // Add the real Advisor/Advice to the chain.
                            // 通过ioc容器或切面实例
                            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;
        }
    

    最终所有配置的切面对象实例都会被放置到AdvisedSupport辅助类的List容器中


    ⚠️addAdvisorOnChainCreation方法会调用DefaultAdvisorAdapterRegistry的wrap

        @Override
        public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
            if (adviceObject instanceof Advisor) {
                return (Advisor) adviceObject;
            }
            //若配置的既不是通知器,也不是advice接口的实现类,抛出异常
            if (!(adviceObject instanceof Advice)) {
                throw new UnknownAdviceTypeException(adviceObject);
            }
            Advice advice = (Advice) adviceObject;
            //将自定义的advice切面封装成通知器
            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);
        }
    

    生成singleton代理对象在getSingletonInstance()方法中完成,这个方法是生成AopProxy代理对象的入口。
    最终通过DefaultAopProxyFactory获取AopProxy
    代码如下

        @Override
        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.");
                }
                //目标类是否是接口类
                if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                    //生成jdk代理对象
                    return new JdkDynamicAopProxy(config);
                }
                //生成cglib代理对象
                return new ObjenesisCglibAopProxy(config);
            }
            else {
                return new JdkDynamicAopProxy(config);
            }
        }
    

    具体的代理对象则有AopProxy(JdkDynamicAopProxy、ObjenesisCglibAopProxy extend CglibAopProxy)类中的getProxy方法来完成。
    我们通过JdkDynamicAopProxy来研究下Proxy的切面拦截策略

    /**
         * Implementation of {@code InvocationHandler.invoke}.
         * <p>Callers will see exactly the exception thrown by the target,
         * unless a hook method throws an exception.
         */
        @Override
        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 {
                //如果没有实现object的基本方法,代理对象会代理生成一个
                if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                    // The target does not implement the equals(Object) method itself.
                    return equals(args[0]);
                }
                if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                    // The target does not implement the hashCode() method itself.
                    return hashCode();
                }
                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;
                }
    
                // 获取目标对象
                target = targetSource.getTarget();
                if (target != null) {
                    targetClass = target.getClass();
                }
    
                // 获取此方法定义好的切面拦截器
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    
                // Check whether we have any advice. If we don't, we can fallback on direct
                // reflective invocation of the target, and avoid creating a MethodInvocation.
                // 如果没有拦截器,直接调用目标方法
                if (chain.isEmpty()) {
                    // We can skip creating a MethodInvocation: just invoke the target directly
                    // Note that the final invoker must be an InvokerInterceptor so we know it does
                    // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
                    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                    retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
                }
                else {
                    // We need to create a method invocation...
                    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.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 chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);获取目标对象的拦截器集合的。
    interceptor链的获取是在DefaultAdvisorChainFactory中实现的

    @Override
        public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
                Advised config, Method method, Class<?> targetClass) {
    
            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) {
                    //获取切点信息
                    PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                    if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                        MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                        MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                        //切点是否符合切面的配置信息
                        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;
        }
    

    返回的interceptorList集合包含了符合此切点的所有切面对象。
    至此,我们已经有了目标对象和所有的切面对象。
    接下来便是依次执行拦截器并执行调用方法
    retVal = invocation.proceed();
    我们跟到ReflectiveMethodInvocation的proceed方法

    @Override
        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;
                if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
                    //若目标方法需要被此拦截器拦截,递归调用拦截器,拦截器的invoke方法中会再次回掉this.proceed方法
                    return dm.interceptor.invoke(this);
                }
                else {
                    // Dynamic matching failed.
                    // Skip this interceptor and invoke the next in the chain.
                    //不需要被此拦截器拦截,直接递归调用this.proceed方法
                    return proceed();
                }
            }
            else {
                // It's an interceptor, so we just invoke it: The pointcut will have
                // been evaluated statically before this object was constructed.
                return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
            }
        }
    
    1. AOP通知实现
      下面有个问题,拦截器有一共有三种,前置,后期,异常,那么interceptorList中的拦截器是如何被区分开的呢?
      下面我们来分析一下,首先我们要从上段代码中关注两行代码
      AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
      MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
      这里的registry是AdvisorAdapterRegistry的一个实现类DefaultAdvisorAdapterRegistry
      我们来具体看看DefaultAdvisorAdapterRegistry的实现
    public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
        //集合中存放了spring aop的3种拦截类型的对象
        private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);
    
        /**
         * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
         */
        public DefaultAdvisorAdapterRegistry() {
            //将前置、后置、异常拦截器对象注册到adapters集合中
            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);
        }
    
        @Override
        public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
            List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
            //获取此通知的切面
            Advice advice = advisor.getAdvice();
            if (advice instanceof MethodInterceptor) {
                interceptors.add((MethodInterceptor) advice);
            }
            //对此切面进行适配,将其封装为已经配置好的AfterReturningAdviceInterceptor,MethodBeforeAdviceInterceptor,ThrowsAdviceInterceptor对象
            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);
        }
    
    }
    

    封装过程以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);
        }
    
    }
    

    最后代理对象就通过调用MethodBeforeAdviceInterceptor中的invoke方法

    这里写图片描述
    public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
    
        private MethodBeforeAdvice advice;
    
        /**
         * Create a new MethodBeforeAdviceInterceptor for the given advice.
         * @param advice the MethodBeforeAdvice to wrap
         */
        public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
            Assert.notNull(advice, "Advice must not be null");
            this.advice = advice;
        }
    
        @Override
        public Object invoke(MethodInvocation mi) throws Throwable {
            //调用前置拦截器、
            this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
            //递归调用ReflectiveMethodInvocation的proceed方法执行拦截器方法
            return mi.proceed();
        }
    
    }
    

    相关文章

      网友评论

          本文标题:spring aop学习总结

          本文链接:https://www.haomeiwen.com/subject/dxajaxtx.html