Spring AOP中通过JDK动态代理的实现原理

AOP相关概念

advice 通知: 定义在切入点织入的行为逻辑(常用device有 BeforeDevice,AfterDevice,ThorwsDevice)

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

《Spring AOP中通过JDK动态代理的实现原理》

《Spring AOP中通过JDK动态代理的实现原理》《Spring AOP中通过JDK动态代理的实现原理》

通过观察Pointcut类的继承关系(向下关系),在Point cut的基本接口定义中可以看到,需要返回一个MethodMatcher;对于Point的匹配判断,具体是有这个返回的MethodMatcher来完成。

Advisor 通知器

当我们完成对目标方法的切面增强设计和关注点的设计后,需要一个对象把他们集合起来,完成这个作用的就是Advisor。

在Spring AOP中常用的Devisor为DefaultPointcutAdvisor

Interceptor 拦截器:

Target 目标对象:被一个或者多个切面所通知的对象。也被称做被通知(advised)对象。 既然Spring AOP是通过运行时代理实现的,这个对象永远是一个被代理(proxied)对象。

Proxy 代理对象:AOP框架创建的对象,用来实现切面契约(例如通知方法执行等等)。在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

Introduction 引入:

Weaving 织入:把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时(例如使用AspectJ编译器),类加载时和运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。

——————————————————————————————————————————–

|接下来我们通过ProxyFactoryBean来深入分析Spring如何通过JDK动态代理实现AOP

<bean id = “testAdvisor” class = “com.dadao.it.aop.TestAdvisor”/>

<bean id =”testAdvice”  class =”com.dadao.it.aop.TestAdvice”/>

<bean id=”testAOP” class=”org.springframework.aop.ProxyFactoryBean”>

    <property name=”proxyInterfaces”>

        <value>com.dadao.it.aop.UserService</value>

    </property>

    <property name=”target”>

        <bean class=”com.dadao.it.aop.UserImpl”/>

    </property>

    <property name=”interceptorNames”>

        <list>

            <value>testAdvisor</value>

            <value>testAdvice</value>

      </list>

    </property>

</bean>

   

——————————————————————————————————————————–

1、ProxyFactoryBean类是一个FactoryBean的Bean,也实现了BeanFactoryAware,因此在Spring初始化ProxyFactoryBean  Bean的

实例时,会将Spring的BeanFactory通过setBeanFactory(BeanFactory beanFactory) 赋值给beanFactory属性

《Spring AOP中通过JDK动态代理的实现原理》

2、由于ProxyFactoryBean是一个FactoryBean,因此提供了一个getObject()的Bean获取方法,通过此方法获取Bean的实例

《Spring AOP中通过JDK动态代理的实现原理》

一、首先会初始化通知器链AdvisorChain,通过this.initializeAdvisorChain();方法初始化

我们进入this.initializeAdvisorChain();方法内部分析通过什么样的规则初始化通知器链,ProxyFactoryBean有个advisorChainInitialized属性标识通知器链是否已经初始化,如果已经初始化了,则直接返回

通过解析interceptorNames指定的值获取通知器链,this.addAdvisorOnChainCreation(advice, name)

调用了DefaultAdvisorAdapterRegistry.wrap()

    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
//如果为Advisor则直接返回
        if (adviceObject instanceof Advisor) {
            return (Advisor)adviceObject;
        } else if (!(adviceObject instanceof Advice)) {
//不是Advisor也不是Advice类型,则直接抛出未知的AdviceType异常
            throw new UnknownAdviceTypeException(adviceObject);
        } else {
//
            Advice advice = (Advice)adviceObject;
            if (advice instanceof MethodInterceptor) {
//如果为MethodInterceptor,则创建DefaultPointcutAdvisor实例封装
                return new DefaultPointcutAdvisor(advice);
            } else {
                Iterator var3 = this.adapters.iterator();

                AdvisorAdapter adapter;
                do {
                    if (!var3.hasNext()) {
                        throw new UnknownAdviceTypeException(advice);
                    }

                    adapter = (AdvisorAdapter)var3.next();
//检查指定的Advice是否注册了可支持的Adapter适配器
                } while(!adapter.supportsAdvice(advice));
//创建DefaultPointcutAdvisor实例封装
                return new DefaultPointcutAdvisor(advice);
            }
        }

    }

下一步添加到Advisor链列表中

private void addAdvisorOnChainCreation(Object next, String name) {
        Advisor advisor = this.namedBeanToAdvisor(next);
        if (this.logger.isTraceEnabled()) {
            this.logger.trace(“Adding advisor with name ‘” + name + “‘”);
        }
//添加到Advisor链列表中
        this.addAdvisor(advisor);

    }

二、通知器链初始化完后,获取Bean实例

   public Object getObject() throws BeansException {
//初始化通知器链
   this.initializeAdvisorChain();
   //判断是否是单例
        if (this.isSingleton()) {
            return this.getSingletonInstance();
        } else {
            if (this.targetName == null) {
                this.logger.warn(“Using non-singleton proxies with singleton targets is often undesirable. Enable prototype proxies by setting the ‘targetName’ property.”);
            }
//非单例
            return this.newPrototypeInstance();
        }

    }

    private synchronized Object getSingletonInstance() {
        if (this.singletonInstance == null) {
            this.targetSource = this.freshTargetSource();
            if (this.autodetectInterfaces && this.getProxiedInterfaces().length == 0 && !this.isProxyTargetClass()) {
                Class<?> targetClass = this.getTargetClass();
                if (targetClass == null) {
                    throw new FactoryBeanNotInitializedException(“Cannot determine target class for proxy”);
                }
                this.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
            }
            super.setFrozen(this.freezeProxy);
//获取代理实例
            this.singletonInstance = this.getProxy(this.createAopProxy());
        }
        return this.singletonInstance;

    }

判断使用JDK动态代理还是CGLIB代理,得到AopProxy对象后,通过调用AopProxy.getProxy()方法就能得到代理对象,《Spring AOP中通过JDK动态代理的实现原理》

JDKDynamicAopProxy为例,调用getProxy(),在此方法中我们就能看到我们非常眼熟的

Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);JDK动态代理创建代理对象的代码

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
//目标类为接口,则使用JDK动态代理
            return new JdkDynamicAopProxy(config);
        } else {
            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.”);
            } else {
                return (AopProxy)(targetClass.isInterface() ? new JdkDynamicAopProxy(config) : new ObjenesisCglibAopProxy(config));
            }
        }

    }

《Spring AOP中通过JDK动态代理的实现原理》

三、有了代理对象以后,当调用代理对象的方法时则会被增强,重点分析JdkDynamicAopProxy.invoke()方法,处理回调

//创建拦截器列表

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

         if (chain.isEmpty()) {

                    //如果没有配置通知器链,则直接调用目标方法

                    retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);

                } else {

    //调用引入的proceed()方法,循环迭代调用拦截器的回调

                    MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);

                    retVal = invocation.proceed();

                }

创建拦截器列表有 DefaultPointcutAdvisor 来负责,具体逻辑如下:

public List<Object> getInterceptorsAndDynamicInterceptioAdvice(Advised config, Method method, Class<?> targetClass) {
        List<Object> interceptorList = new ArrayList(config.getAdvisors().length);
        boolean hasIntroductions = hasMatchingIntroductions(config, targetClass);
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
        Advisor[] var7 = config.getAdvisors();
        int var8 = var7.length;

        for(int var9 = 0; var9 < var8; ++var9) {
            Advisor advisor = var7[var9];
            MethodInterceptor[] interceptors;
//通知器为PointcutAdvisor(Advice会被封装成DefaultPointcutAdvisor)
            if (advisor instanceof PointcutAdvisor) {
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor)advisor;
                if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
                    interceptors = registry.getInterceptors(advisor);
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) {
                        if (mm.isRuntime()) {
                            MethodInterceptor[] var14 = interceptors;
                            int var15 = interceptors.length;

                            for(int var16 = 0; var16 < var15; ++var16) {
                                MethodInterceptor interceptor = var14[var16];
//使用InterceptorAndDynamicMethodMatcher封装,具体matcher的能力
                                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)) {
                    interceptors = registry.getInterceptors(advisor);
                    interceptorList.addAll(Arrays.asList(interceptors));
                }
            } else {
//直接加入拦截器列表里
                Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
        }
        return interceptorList;
    }

调用ReflectiveMethodInvocation.proceed()函数迭代调用拦截器,直到拦截器链中的拦截器都完成拦截过程为止

    public Object proceed() throws Throwable {
//拦截器为最后一个,则直接调用目标方法
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() – 1) {
            return this.invokeJoinpoint();
        } else {
            Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
            if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
    //检查拦截器的切入点是否匹配调用方法,如果匹配则调用拦截器的invoke(),如果不匹配则递归调用proceed()函数,直到所有拦截器都被运行过为止
                InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
                return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
            } else {
//直接调用拦截器invoke()
                return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
            }
        }

    }

~~~~到目前为止,就分析完了!

    原文作者:AOP
    原文地址: https://blog.csdn.net/supportUAT/article/details/79829475
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞