spring系列文章(一)AOP源码分析

 2019-11-23 11:13  阅读(1119)
文章分类:Spring Cloud

BeanNameAutoProxyCreator与ProxyFactoryBean区别

我们项目用到的是BeanNameAutoProxyCreator,说道aop可能大家更熟悉的是ProxyFactoryBean。它们的区别很简单,BeanNameAutoProxyCreator只不过可以配置多个target

使用

配置中有两个参数:

  • beanNames:要拦截的bean
  • interceptorNames:拦截器

配置示例:

<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" id="ims_core_new_ServiceAutoProxy">
            <property name="beanNames">
                <list>
                    <!--需要拦截的服务-->
                    <value>imsinner_innerService</value>
                    <value>imsinner_innerQueryService</value>
                    <value>imssdl_iImsSyncAppService</value>
                    <value>imsts_iImsTsAppService</value>
                    <value>imsxdr_iImsXdrService</value>
                </list>
            </property>
            <property name="interceptorNames">
                <list>
                    <value>ims_new_interceptor</value>
                </list>
            </property>
        </bean>

源码分析

那么重点就是来看下BeanNameAutoProxyCreator了

public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {
    }

AbstractAutoProxyCreator里几个重要的属性

private String interceptorNames[];
    private BeanFactory beanFactory;
    private ClassLoader proxyClassLoader;

凭直觉,createProxy应该是一个重要的方法,分析一下

protected Object createProxy(Class beanClass, String beanName, Object specificInterceptors[], TargetSource targetSource)
        {
            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.copyFrom(this);
            if(!shouldProxyTargetClass(beanClass, beanName))
            {
                Class targetInterfaces[] = ClassUtils.getAllInterfacesForClass(beanClass, proxyClassLoader);
                Class aclass[];
                int k = (aclass = targetInterfaces).length;
                for(int i = 0; i < k; i++)
                {
                    Class targetInterface = aclass[i];
                    proxyFactory.addInterface(targetInterface);
                }

            }
            Advisor advisors[] = buildAdvisors(beanName, specificInterceptors);
            Advisor aadvisor[];
            int l = (aadvisor = advisors).length;
            for(int j = 0; j < l; j++)
            {
                Advisor advisor = aadvisor[j];
                proxyFactory.addAdvisor(advisor);
            }

            proxyFactory.setTargetSource(targetSource);
            customizeProxyFactory(proxyFactory);
            proxyFactory.setFrozen(freezeProxy);
            if(advisorsPreFiltered())
                proxyFactory.setPreFiltered(true);
            return proxyFactory.getProxy(proxyClassLoader);
    }

一路追踪到了这个方法

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())
                    return new JdkDynamicAopProxy(config);
                if(!cglibAvailable)
                    throw new AopConfigException("Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.");
                else
                    return CglibProxyFactory.createCglibProxy(config);
            } else
            {
                return new JdkDynamicAopProxy(config);
            }
        }

JdkDynamicAopProxy 的getProxy如下

public Object getProxy(ClassLoader classLoader)
        {
            if(logger.isDebugEnabled())
                logger.debug((new StringBuilder("Creating JDK dynamic proxy: target source is ")).append(advised.getTargetSource()).toString());
            Class proxiedInterfaces[] = AopProxyUtils.completeProxiedInterfaces(advised);
            findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
            return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

到这里我们就看到了创建jdk的proxy代理

这里我们的JdkDynamicAopProxy实现了InvocationHandler这个接口,this参数对应的是InvocationHandler对象,也就是说当 Proxy对象的函数被调用的时候,InvocationHandler的invoke方法会被作为回调函数调用:下面也有一个回调的分析。

分析到这里关键就看下invoke方法了

这里得到一个拦截器链

List chain = advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

if(chain.isEmpty())
            {
                //如果拦截器为空,则直接调用被代理的方法
    retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
            } else
            {
    //拦截器不为空,则 
    MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                retVal = invocation.proceed();
            }

public static Object invokeJoinpointUsingReflection(Object target, Method method, Object args[])
            throws Throwable
        {
            ReflectionUtils.makeAccessible(method);
            return method.invoke(target, args);
            InvocationTargetException ex;
            ex;
            throw ex.getTargetException();
            ex;
            throw new AopInvocationException((new StringBuilder("AOP configuration seems to be invalid: tried calling method [")).append(method).append("] on target [").append(target).append("]").toString(), ex);
            ex;
            throw new AopInvocationException((new StringBuilder("Could not access method [")).append(method).append("]").toString(), ex);
        }

public Object proceed()
            throws Throwable
    {
        //已经没有拦截器要调用了,则直接调用主方法
            if(currentInterceptorIndex == interceptorsAndDynamicMethodMatchers.size() - 1)
                return invokeJoinpoint();
            Object interceptorOrInterceptionAdvice = interceptorsAndDynamicMethodMatchers.get(++currentInterceptorIndex);
            if(interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher)
            {
                InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
                if(dm.methodMatcher.matches(method, targetClass, arguments))
                    return dm.interceptor.invoke(this);
                else
                    return proceed();
            } else
            {
                return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
            }
    }

这里有一个什么匹配的逻辑,如果匹配,调用这个拦截器,如果不匹配,继续下一个拦截器,这个匹配就不细看了

那如果匹配了,下一个就不走了?
挺关键的这个地方,这个ReflectiveMethodInvocation实现了MethodInvocation接口,在调用拦截器的invoke的方法的时候,把自己做为参数传给了拦截器,在拦截器A执行完以后,如果想继续执行拦截器链的下一个,只需要在它实现的invoke方法的proceed方法,就可以回调proceed,继续执行下一个

return dm.interceptor.invoke(this);

       public Object invoke(MethodInvocation invocation) throws Throwable

总结

在整个的分析过程中,可以看到理解了这么几个技术点,基本上就理解了AOP

  • 动态代理
  • 责任链
  • 回调

当然还有spring最基本的工厂模式,太基本了就不罗列它了。


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

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> spring系列文章(一)AOP源码分析

相关推荐