spring源码阅读(2)-aop之源码解析篇

 2019-11-23 11:14  阅读(1159)
文章分类:Spring Cloud

经过一个aop术语介绍和动态代理的深入讲解,我们终于可以来看aop的源码了,下面跟着博主一点点剖析spring aop源码的实现吧

我们知道spring使用中我们只要做好相关的配置,spring自动帮我们做好了代理的相关工作。

我们从三个方面入手吧

1、配置

2、创建代理

3、获取代理类

配置

我们从AopNamespaceHandler入手,这个是自定义配置的实现类

public void init() {
            this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
            this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        }

对aop的aspectj的配置很熟悉了吧

我们来看看AspectJAutoProxyBeanDefinitionParser的parse方法吧,这个是ioc加载自定义配置调用的方法

public BeanDefinition parse(Element element, ParserContext parserContext) {
            AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
        }

    public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
                ParserContext parserContext, Element sourceElement) {
            //注册AspectJAnnotationAutoProxyCreator
            BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
                    parserContext.getRegistry(), parserContext.extractSource(sourceElement));
            //处理proxy-target-class和expose-proxy

            useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
        //注册组件
            registerComponentIfNecessary(beanDefinition, parserContext);
        }

            //注册的是AnnotationAwareAspectJAutoProxyCreator
    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
            return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
        }

这里我们注意,springaop自动帮我们注册了AnnotationAwareAspectJAutoProxyCreator

另外target-proxy-class:spring提供了两种代理的,jdk和cglib(建议使用jdk),这个属性就是配置使用哪个代理模式的true-cglib,false-jdk

expose-proxy:解决那日不自我调用无法增强

创建代理

我们看看AnnotationAwareAspectJAutoProxyCreator的UML类关系图

20191123100340\_1.png

可以看出AbstractAutoProxyCreator实现了BeanPostProcessor方法,看到这个我想我们应该知道去关注什么方法吧,对postProcessAfterInitialization是创建bean的时候会执行的方法

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (bean != null) {
                Object cacheKey = getCacheKey(bean.getClass(), beanName);
                if (!this.earlyProxyReferences.containsKey(cacheKey)) {
                    return wrapIfNecessary(bean, beanName, cacheKey);
                }
            }
            return bean;
        }

什么缓存之类的我们先不看了,因为这个时候还没有

if (beanName != null && this.targetSourcedBeans.containsKey(beanName)) {
                return bean;
            }

            // 获取bean的切面
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
            if (specificInterceptors != DO_NOT_PROXY) {
                //创建代理对象
                Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            }

            return bean;
    }

我们先来看看增强的获取:

1、
    protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) {
            List advisors = findEligibleAdvisors(beanClass, beanName);
            if (advisors.isEmpty()) {
                return DO_NOT_PROXY;
            }
            return advisors.toArray();
        }

    2、
    protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {
               //寻找所有的增强
            List<Advisor> candidateAdvisors = findCandidateAdvisors();
            //匹配适应的增强,无法找到返回null
            List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
            extendAdvisors(eligibleAdvisors);
            if (!eligibleAdvisors.isEmpty()) {
                //排序增强
                eligibleAdvisors = sortAdvisors(eligibleAdvisors);
            }
            return eligibleAdvisors;
        }

在过来看看代理的创建

protected Object createProxy(
                Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

            ProxyFactory proxyFactory = new ProxyFactory();

            //添加代理接口
            if (!shouldProxyTargetClass(beanClass, beanName)) {
                // Must allow for introductions; can't just set interfaces to
                // the target's interfaces only.
                Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
                for (Class<?> targetInterface : targetInterfaces) {
                    proxyFactory.addInterface(targetInterface);
                }
            }
            //添加增强
            Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
            for (Advisor advisor : advisors) {
                proxyFactory.addAdvisor(advisor);
            }

            proxyFactory.setTargetSource(targetSource);

            return proxyFactory.getProxy(this.proxyClassLoader);
        }

直接看getProxy()

public Object getProxy(ClassLoader classLoader) {
            return createAopProxy().getProxy(classLoader);
        }

我先看看createAopFactory创建了什么代理类

protected final synchronized AopProxy createAopProxy() {
            if (!this.active) {
                activate();
            }
            return getAopProxyFactory().createAopProxy(this);
        }

    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
            //判断配置,optimize配置为true或者proxy-target-class=true
            //且目标类是一个接口使用jdk
            //或者使用cglib
            if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
                Class targetClass = config.getTargetClass();

                if (targetClass.isInterface()) {
                    return new JdkDynamicAopProxy(config);
                }
                return CglibProxyFactory.createCglibProxy(config);
            }
            //optimize配置为false并且proxy-target-class=false直接使用jdk代理
            else {
                return new JdkDynamicAopProxy(config);
            }
        }

看到了吧,这里就决定了代理的创建方式,optimize为false且proxy-target-class=false,且不存在使用代理接口直接使用jdk,否则再判断如果目标类是一个接口,则使用jdk,否则使用cglib。

先剖析Jdk的getProxy

我们来看下JdkDynamicAopProxy的类关系图

20191123100340\_2.png

从上图可知,JdkDynamicAopProxy实现了InvocationHandler,也就是代理的逻辑操作在这里面实现

再看看getProxy这个函数

public Object getProxy(ClassLoader classLoader) {

            Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
            findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
            return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
        }

这里的return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);就是创建代理类了

我们看看jdk的关键InvocationHandler的实现吧

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                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;
                }

                // May be null. Get as late as possible to minimize the time we "own" the target,
                // in case it comes from a pool.
                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()) {
                    //没有拦截链直接调用方法
                    retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
                }
                else {
                    // 封装拦截链
                    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;
            }

        }

这里比较重要的就是拦截链了,我们接下来剖析一下拦截链的执行

public Object proceed() throws Throwable {
            //  执行完所有拦截器链后,执行切点方法
            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)) {
                    return dm.interceptor.invoke(this);
                }
                else {
                    //匹配失败,不执行啥
                    return proceed();
                }
            }
            else {
                //普通拦截器直接调用拦截器,处理引介增强
                return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
            }
        }

这里就是通过一个索引遍历列表的,注意一下这个InterceptorAndDynamicMethodMatcher类

class InterceptorAndDynamicMethodMatcher {

        final MethodInterceptor interceptor;

        final MethodMatcher methodMatcher;

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

    }

其实就是一个方法匹配拦截器,这里我们在回到上面的创建拦截器链的方法,看看怎么创建拦截器的

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

            List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);

            //获取所有的增强器
            for (Advisor advisor : config.getAdvisors()) {
                //判断增强是否有切点
                if (advisor instanceof PointcutAdvisor) {

                    PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                    if (config.isPreFiltered() || 
                    //类过滤器匹配
    pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
                        MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                        MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                        //方法匹配器匹配
                        if (MethodMatchers.matches(mm, method, targetClass, 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(targetClass)) {
                        Interceptor[] interceptors = registry.getInterceptors(advisor);
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
                //普通方法
                else {
                    Interceptor[] interceptors = registry.getInterceptors(advisor);
                    interceptorList.addAll(Arrays.asList(interceptors));
                }
            }
            return interceptorList;
        }

其实这个拦截器链的处理和process()加起来就决定了哪些增强方法会被处理。

Cglib

public Object getProxy(ClassLoader classLoader) {

                Class<?> rootClass = this.advised.getTargetClass();

                Class<?> proxySuperClass = rootClass;
                if (ClassUtils.isCglibProxyClass(rootClass)) {
                    proxySuperClass = rootClass.getSuperclass();
                    Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                    for (Class<?> additionalInterface : additionalInterfaces) {
                        this.advised.addInterface(additionalInterface);
                    }
                }

                Enhancer enhancer = createEnhancer();

                enhancer.setSuperclass(proxySuperClass);
                enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
                enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
                enhancer.setStrategy(new MemorySafeUndeclaredThrowableStrategy(UndeclaredThrowableException.class));
                enhancer.setInterceptDuringConstruction(false);
    //获取回调
                Callback[] callbacks = getCallbacks(rootClass);
                Class<?>[] types = new Class<?>[callbacks.length];
                for (int x = 0; x < types.length; x++) {
                    types[x] = callbacks[x].getClass();
                }
                enhancer.setCallbackFilter(new ProxyCallbackFilter(
                        this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
                enhancer.setCallbackTypes(types);
    //设置回调
                enhancer.setCallbacks(callbacks);

                //创建代理类
                proxy = enhancer.create();

                return proxy;
        }

上面代码一目了然了,基本上就是一个cglib动态代理的配置创建代码,我们需要想jdk部分那样找到代理的处理部分,在cglib中是callback

getCallBack

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

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

                    if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {

                        retVal = methodProxy.invoke(target, args);
                    }
                    else {

                        retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
                    }
                    retVal = processReturnType(proxy, target, method, retVal);
                    return retVal;
            }

基本和jdk的流程差不多,首先创建一个拦截器链,然后遍历。

至此aop的源码我们分析完毕,我们来做个总结吧:

1、springaop默认使用的是jdk的代理方式,如果想使用cglib,可配置

2、这里有必要提一提jdk的运行性能没有cglib高,比cglib差8倍,但创建代理的性能比cglib高10倍,对于无需频繁创建代理比较适合使用cglib模式,反之jdk模式比较适合

3、jdk和cglib都是运行时创建代理的方式


来源:http://ddrv.cn/a/88268

点赞(1)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> spring源码阅读(2)-aop之源码解析篇

相关推荐