美文网首页
Spring aop解析(4)2018-08-14

Spring aop解析(4)2018-08-14

作者: Seetheworl_6675 | 来源:发表于2018-08-15 19:28 被阅读0次

    上一节我们分析了Advisor的生成过程以及在Advisor中生成Advise的过程。接着上一节继续我们看看挑出适用于目标对象的Advisor:

    private void addAdvisorsFromAspectInstanceFactory(MetadataAwareAspectInstanceFactory instanceFactory) {
            //获取Advisors集合
            List<Advisor> advisors = this.aspectFactory.getAdvisors(instanceFactory);
            //从中挑出适用于目标对象的Advisor
            advisors = AopUtils.findAdvisorsThatCanApply(advisors, getTargetClass());
            AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(advisors);
            //对获取到的Advisor进行排序
            AnnotationAwareOrderComparator.sort(advisors);
            //将获取到Advisor添加到advisors集合中
            addAdvisors(advisors);
        }
    
    2.3.1:addAdvisorsFromAspectInstanceFactory方法:

    a、挑出适用于目标对象的Advisor: AopUtils.findAdvisorsThatCanApply(advisors, getTargetClass());

    public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
            //如果传入的Advisor集合为空的话,直接返回这个空集合
            if (candidateAdvisors.isEmpty()) {
                return candidateAdvisors;
            }
            //创建一个合适的Advisor的集合 eligible
            List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
            //循环所有的Advisor
            for (Advisor candidate : candidateAdvisors) {
                //如果Advisor是IntroductionAdvisor  引介增强 可以为目标类 通过AOP的方式添加一些接口实现
                if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
                    eligibleAdvisors.add(candidate);
                }
            }
            //是否有引介增强
            boolean hasIntroductions = !eligibleAdvisors.isEmpty();
            for (Advisor candidate : candidateAdvisors) {
                //如果是IntroductionAdvisor类型的话 则直接跳过
                if (candidate instanceof IntroductionAdvisor) {
                    // already processed
                    continue;
                }
                //判断此Advisor是否适用于target
                if (canApply(candidate, clazz, hasIntroductions)) {
                    eligibleAdvisors.add(candidate);
                }
            }
            return eligibleAdvisors;
        }
    
    public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
            //如果是IntroductionAdvisor的话,则调用IntroductionAdvisor类型的实例进行类的过滤
            //这里是直接调用的ClassFilter的matches方法
            if (advisor instanceof IntroductionAdvisor) {
                return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
            }
            //通常我们的Advisor都是PointcutAdvisor类型
            else if (advisor instanceof PointcutAdvisor) {
                PointcutAdvisor pca = (PointcutAdvisor) advisor;
                //这里从Advisor中获取Pointcut的实现类 这里是AspectJExpressionPointcut
                return canApply(pca.getPointcut(), targetClass, hasIntroductions);
            }
            else {
                // It doesn't have a pointcut so we assume it applies.
                return true;
            }
        }
    

    这里匹配的规则我们就不进行深入了。

    2.4:接着我们来看看代理对象的创建过程:
    public class TestAop {
        public static void main(String[] args) {
            //手工创建一个实例(Target)
            ProxyService aspectJService = new ProxyServiceImpl();
            //使用AspectJ语法 自动创建代理对象
            AspectJProxyFactory aspectJProxyFactory = new AspectJProxyFactory(aspectJService);
            //添加切面和通知类
            aspectJProxyFactory.addAspect(AopAdviceConfig.class);
            //创建代理对象
            ProxyService proxyService = aspectJProxyFactory.getProxy();
            //进行方法调用
            proxyService.testProxy();
        }
    }
    

    a、创建代理aspectJProxyFactory.getProxy():

     //通过调用createAopProxy()生成的对象调用getProxy()方法生成代理对象
     public <T> T getProxy() {
            return (T) createAopProxy().getProxy();
    }
    
    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            //这里会监听调用AdvisedSupportListener实现类的activated方法
            activate();
        }
        //获取AopProxyFactory
        //调用createAopProxy的时候传入了this对象
        return getAopProxyFactory().createAopProxy(this);
    }
    //在SpringAOP中 AopProxyFactory只有一个实现类,这个实现类就是DefaultAopProxyFactory
    public AopProxyFactory getAopProxyFactory() {
        return this.aopProxyFactory;
    }   
    
    private void activate() {
            this.active = true;
            for (AdvisedSupportListener listener : this.listeners) {
                listener.activated(this);
            }
        }
    

    b、我们接着看:createAopProxy()方法:

    ublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
            //这段代码用来判断选择哪种创建代理对象的方式
            //config.isOptimize()   是否对代理类的生成使用策略优化 其作用是和isProxyTargetClass是一样的 默认为false
            //config.isProxyTargetClass() 是否使用Cglib的方式创建代理对象 默认为false
            //hasNoUserSuppliedProxyInterfaces目标类是否有接口存在 且只有一个接口的时候接口类型不是SpringProxy类型 
            if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
                //从AdvisedSupport中获取目标类 类对象
                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类型 则还是使用JDK的方式生成代理对象
                if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                    return new JdkDynamicAopProxy(config);
                }
                return new ObjenesisCglibAopProxy(config);
            }
            else {
                //使用JDK的提供的代理方式生成代理对象
                return new JdkDynamicAopProxy(config);
            }
        }
    
    

    c、我们接着往下看看createAopProxy().getProxy()方法:

    public <T> T getProxy(ClassLoader classLoader) {
           return (T) createAopProxy().getProxy(classLoader);
       }
    
    public Object getProxy(ClassLoader classLoader) {
           if (logger.isDebugEnabled()) {
               logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
           }
           //获取AdvisedSupport类型对象的所有接口
           Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
           //接口是否定义了 equals和hashcode方法 正常是没有的,定义了生成的代理以定义的为准
           findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
           //创建代理
           return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
       }
    
    private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
           for (Class<?> proxiedInterface : proxiedInterfaces) {
               Method[] methods = proxiedInterface.getDeclaredMethods();
               for (Method method : methods) {
                   if (AopUtils.isEqualsMethod(method)) {
                       this.equalsDefined = true;
                   }
                   if (AopUtils.isHashCodeMethod(method)) {
                       this.hashCodeDefined = true;
                   }
                   if (this.equalsDefined && this.hashCodeDefined) {
                       return;
                   }
               }
           }
       }
    

    e、我们知道创建代理需要额外功能类继承InvocationHandler实现invoke方法添加额外功能,那么我们来看看JdkDynamicAopProxy中的invoke的实现:

    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 {
                //接口中没有定义 equals方法,并且调用的方法是equals方法(即Object中定义的equals方法) 
                if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                    //调用 JdkDynamicAopProxy 中写的equals方法
                    return equals(args[0]);
                }else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                    //和上面的分析一样
                    return hashCode();
                }else if (method.getDeclaringClass() == DecoratingProxy.class) {
                    return AopProxyUtils.ultimateTargetClass(this.advised);
                }else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                  //如果 方法所在的类是接口 并且是Advised的子类,则直接调用下面的方法
                    return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
                }
    
                Object retVal;
                //是否对外暴露代理对象
                if (this.advised.exposeProxy) {
                    // Make invocation available if necessary.
                    //把创建的代理对象放到线程上下文中返回之前老的代理
                    oldProxy = AopContext.setCurrentProxy(proxy);
                    setProxyContext = true;
                }
                //从TargetSource中获取目标对象
                target = targetSource.getTarget();
                if (target != null) {
                    targetClass = target.getClass();
                }
                //从Advised中根据方法名和目标类获取 AOP拦截器执行链 重点要分析的内容
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                //如果这个执行链为空的话
                if (chain.isEmpty()) {
                    //直接进行方法调用
                    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                    retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
                }
                else {
                    //如果AOP拦截器执行链不为空  说明有AOP通知存在
                    invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                    //开始调用
                    retVal = invocation.proceed();
                }
                //方法的返回值类型
                Class<?> returnType = method.getReturnType();
                if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
                        !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                    //return this
                    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 {
                //如果目标对象不为空  且目标对象是可变的 如prototype类型
                //通常我们的目标对象都是单例的  即targetSource.isStatic为true
                if (target != null && !targetSource.isStatic()) {
                    //释放目标对象
                    targetSource.releaseTarget(target);
                }
                if (setProxyContext) {
                    //线程上下文复位
                    AopContext.setCurrentProxy(oldProxy);
                }
            }
        }
    

    从上面代码不难看出这段代码的重点:从Advised中根据方法名和目标类获取 AOP拦截器执行链(List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);)那么我们来看看获取的代码:

    f、this.advised.getInterceptorsAndDynamicInterceptionAdvice:

    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
            //创建一个method的缓存对象在MethodCacheKey中实现了equals和hashcode方法同时还实现了compareTo方法
            MethodCacheKey cacheKey = new MethodCacheKey(method);
            List<Object> cached = this.methodCache.get(cacheKey);
            //先从缓存中获取 如果缓存中获取不到则再调用方法获取,获取之后放入到缓存中
            if (cached == null) {
                //调用的是advisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法
                cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
                        this, method, targetClass);
                this.methodCache.put(cacheKey, cached);
            }
            return cached;
        }
    
    
    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
                Advised config, Method method, Class<?> targetClass) {
            //创建一个初始大小为之前获取到的 通知个数的 集合
            List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
            //如果目标类为null的话,则从方法签名中获取目标类
            Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
            //判断目标类是否存在引介增强通常为false
            boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
            //这里用了一个单例模式获取DefaultAdvisorAdapterRegistry实例
            AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
            //循环目标方法匹配的通知
            for (Advisor advisor : config.getAdvisors()) {
                //如果是PointcutAdvisor类型的实例  我们大多数的Advisor都是PointcutAdvisor类型的
                if (advisor instanceof PointcutAdvisor) {
                    PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                    //如果提前进行过 切点的匹配了或者当前的Advisor适用于目标类
                    if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                        //将Advisor适配为MethodInterceptor
                        MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                        MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                        //检测Advisor是否适用于此目标方法
                        if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
                            //MethodMatcher中的切点分为两种 一个是静态的 一种是动态的
                            //如果isRuntime返回true 则是动态的切入点每次方法的调用都要去进行匹配
                            //而静态切入点则回缓存之前的匹配结果值 
                            if (mm.isRuntime()) {
                                //动态切入点 则会创建一个InterceptorAndDynamicMethodMatcher对象
                                //这个对象包含MethodInterceptor和MethodMatcher 的实例
                                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)) {
                        //将Advisor转换为Interceptor
                        Interceptor[] interceptors = registry.getInterceptors(advisor);
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
                //以上两种都不是
                else {
                    //将Advisor转换为Interceptor
                    Interceptor[] interceptors = registry.getInterceptors(advisor);
                    interceptorList.addAll(Arrays.asList(interceptors));
                }
            }
            return interceptorList;
        }
    

    从上面代码可以总结下流程:
    1、循环目标方法的所有Advisor
    2、判断Advisor的类型
      a、如果是PointcutAdvisor的类型,则判断此Advisor是否适用于此目标方法
     b、如果是IntroductionAdvisor引介增强类型,则判断此Advisor是否适用于此目标方法
     c、如果以上都不是,则直接转换为Interceptor类型。

    不管是Advisor哪一类型最终都会registry.getInterceptors(advisor);进行转换,那么我们来看看这个方法:

    g、registry.getInterceptors(advisor):
    我们来先看看registry的获取代码:

     AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
    =========
    public abstract class GlobalAdvisorAdapterRegistry {
        private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();
    
        
        public static AdvisorAdapterRegistry getInstance() {
            return instance;
        }
    =========
    public DefaultAdvisorAdapterRegistry() {
            //前置通知适配器
            registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
            //后置返回通知适配器
            registerAdvisorAdapter(new AfterReturningAdviceAdapter());
            //后置异常通知适配器
            registerAdvisorAdapter(new ThrowsAdviceAdapter());
        }
    

    接着我们来看看:registry.getInterceptors的代码:

    public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
            List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
            //从Advisor中获取 Advice
            Advice advice = advisor.getAdvice();
            if (advice instanceof MethodInterceptor) {
                interceptors.add((MethodInterceptor) advice);
            }
            for (AdvisorAdapter adapter : this.adapters) {
                if (adapter.supportsAdvice(advice)) {
                    //转换为对应的 MethodInterceptor类型
                    //AfterReturningAdviceInterceptor MethodBeforeAdviceInterceptor  ThrowsAdviceInterceptor
                    interceptors.add(adapter.getInterceptor(advisor));
                }
            }
            if (interceptors.isEmpty()) {
                throw new UnknownAdviceTypeException(advisor.getAdvice());
            }
            return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
        }
    

    l、拦截器连的调用过程:
    invoke方法中的:

    //如果AOP拦截器执行链不为空  说明有AOP通知存在
     invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
    //开始调用
     retVal = invocation.proceed();
    

    那么我们来看看这个方法:

    public Object proceed() throws Throwable {
            // 如果执行到链条的末尾则直接调用连接点方法即直接调用目标方法
            if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
                //调用目标方法
                return invokeJoinpoint();
            }
            //获取集合中的 MethodInterceptor
            Object interceptorOrInterceptionAdvice =
                    this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
            //如果是InterceptorAndDynamicMethodMatcher类型
            if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
                InterceptorAndDynamicMethodMatcher dm =
                        (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
                //这里每一次都去匹配是否适用于这个目标方法
                if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
                    //如果匹配则直接调用 MethodInterceptor的invoke方法
                    return dm.interceptor.invoke(this);
                }
                else {
                    //如果不适用于此目标方法 则继续执行下一个链条 递归调用
                    return proceed();
                }
            }
            else {
                //直接调用 MethodInterceptor的invoke方法 
                return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
            }
        }
    

    看下invokeJoinpoint方法(直接掉用目标类的方法):

    protected Object invokeJoinpoint() throws Throwable {
            //this.target 目标对象
            //this.method 目标方法
            this.arguments 目标方法参数信息
            return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
        }
        public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
                throws Throwable {
    
            // Use reflection to invoke the method.
            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);
            }
        }
    

    相关文章

      网友评论

          本文标题:Spring aop解析(4)2018-08-14

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