美文网首页
获取spring aop 代理目标类

获取spring aop 代理目标类

作者: 全都是泡沫啦 | 来源:发表于2019-03-14 11:08 被阅读0次

工作中过程中需要使用aop,spring中帮我们封装了特别好用的代理工具类ProxyFactory ,有时我们需要获取代理的目标类,于是乎就有了下面的代码。网上有许多大部分都是通过反射获取,他们忽略了ProxyFactory 已经为我们提供了特别方便的获取方式,就是在代理生成类中添加了org.springframework.aop.framework.Advised的实现,帮我们更容易的获取目标对象。以下代码也支持获取重复代理目标类

package com.paulzhangcc.gateway.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.framework.AopProxy;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.cglib.core.DebuggingClassWriter;

import java.lang.reflect.Field;
import java.util.ArrayList;

/**
 * @author paul
 * @description
 * @date 2019/3/13
 */
public class AopTargetUtils {
    private final static Logger logger = LoggerFactory.getLogger(AopTargetUtils.class);

    public static Object getTarget(Object proxy) {
        if (proxy == null) {
            return null;
        }
        if (!AopUtils.isAopProxy(proxy)) {
            return proxy;
        }
        return getTarget(_getTarget(proxy));
    }


    private static Object _getTarget(Object proxy) {
        if (proxy instanceof Advised) {
            TargetSource targetSource = ((Advised) proxy).getTargetSource();
            try {
                logger.info("get target object from Advised#getTargetSource["+proxy.getClass().getName()+"]");
                return targetSource == null ? null : targetSource.getTarget();
            } catch (Exception e) {
                logger.error("get target object from Advised#getTargetSource["+proxy.getClass().getName()+"] error", e);
            }
        }
        if (AopUtils.isCglibProxy(proxy)) {
            try {
                return getCglibProxyTargetObject(proxy);
            } catch (Exception e) {
                logger.error("get target object from Cglib ["+proxy.getClass().getName()+"] error", e);
            }
        } else if (AopUtils.isJdkDynamicProxy(proxy)) {
            try {
                return getJdkDynamicProxyTargetObject(proxy);
            } catch (Exception e) {
                logger.error("get target object from Jdk ["+proxy.getClass().getName()+"] error", e);
            }
        }
        return null;
    }

    private static Object getCglibProxyTargetObject(Object proxy) throws Exception {
        Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
        h.setAccessible(true);
        Object dynamicAdvisedInterceptor = h.get(proxy);
        Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
        advised.setAccessible(true);
        Object target = ((AdvisedSupport) advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();
        logger.info("get target object ["+target.getClass().getName()+"] from Cglib reflect ,from proxy:"+proxy.getClass().getName());
        return target;
    }

    private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception {
        Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
        h.setAccessible(true);
        AopProxy aopProxy = (AopProxy) h.get(proxy);
        Field advised = aopProxy.getClass().getDeclaredField("advised");
        advised.setAccessible(true);
        Object target = ((AdvisedSupport) advised.get(aopProxy)).getTargetSource().getTarget();
        logger.info("get target object ["+target.getClass().getName()+"] from Jdk reflect ,from proxy:"+proxy.getClass().getName());
        return target;
    }

    public static void main(String[] args) {
        //一下测试结果包含重复代理生成类
        {
            //cglib proxy from Advised#getTargetSource
            System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "F:\\code\\spring-cloud\\spring-cloud-quick-start\\spring-cloud-gateway\\target");
            Person person = new Person();
            ProxyFactory proxyFactory = new ProxyFactory(person);
            Object proxy = proxyFactory.getProxy();
            System.out.println(person == getTarget(proxy));

            ProxyFactory proxyFactory1 = new ProxyFactory(proxy);
            Object proxy1 = proxyFactory1.getProxy();
            System.out.println(person == getTarget(proxy1));
        }

        {
            //jdk proxy from Advised#getTargetSource
            System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
            ArrayList arrayList = new ArrayList();
            ProxyFactory proxyFactory = new ProxyFactory(arrayList);
            Object proxy = proxyFactory.getProxy();
            System.out.println(arrayList == getTarget(proxy));

            ProxyFactory proxyFactory1 = new ProxyFactory(proxy);
            Object proxy1 = proxyFactory1.getProxy();
            System.out.println(arrayList == getTarget(proxy1));
        }

        {
            //cglib proxy from reflection
            System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "F:\\code\\spring-cloud\\spring-cloud-quick-start\\spring-cloud-gateway\\target");
            Person person = new Person();
            ProxyFactory proxyFactory = new ProxyFactory(person);
            proxyFactory.setOpaque(true);
            Object proxy = proxyFactory.getProxy();
            System.out.println(person == getTarget(proxy));

            ProxyFactory proxyFactory1 = new ProxyFactory(proxy);
            proxyFactory1.setOpaque(true);
            Object proxy1 = proxyFactory1.getProxy();
            System.out.println(person == getTarget(proxy1));
        }

        {
            //jdk proxy from reflection
            System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
            ArrayList arrayList = new ArrayList();
            ProxyFactory proxyFactory = new ProxyFactory(arrayList);
            proxyFactory.setOpaque(true);
            Object proxy = proxyFactory.getProxy();
            System.out.println(arrayList == getTarget(proxy));

            ProxyFactory proxyFactory1 = new ProxyFactory(proxy);
            proxyFactory1.setOpaque(true);
            Object proxy1 = proxyFactory1.getProxy();
            System.out.println(arrayList == getTarget(proxy1));
        }

    }

    public static class Person {
        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        String name;
    }

}

相关文章

  • 获取spring aop 代理目标类

    工作中过程中需要使用aop,spring中帮我们封装了特别好用的代理工具类ProxyFactory ,有时我们需要...

  • spring aop获取代理目标对象

    spring aop获取代理目标对象 转载: https://coget.cn/archives/spring%2...

  • Spring AOP 学习笔记(1) ---- 代理模式

    参考文章 spring aop 官方文档 掘金spring aop 教程 掘金动态代理 代理模式分类 根据代理类的...

  • Spring AOP

    Spring AOP是代理模式的经典实现,代理模式的作用就是把一些目标类没有的功能附加到代理类上,然后在代理类上执...

  • Spring AOP内部调用失效问题

    Spring AOP基本原理 Spring AOP是基于动态代理机制实现的,通过动态代理机制生成目标对象的代理对象...

  • AOP代理:

    AOP代理:AOP框架创建的对象,代理就是对目标对象的增强。Spring中的AOP代理可以是JDK动态代理,也可以...

  • spring aop 汇总

    静态代理、动态代理和cglib代理 aop 使用 Spring AOP - 注解方式使用介绍spring aop ...

  • AOP-AspectJ / JDK Proxy / CGLIB

    Spring AOP采用动态代理的方式,在运行期生成代理类来实现AOP,不修改原类的实现 Aspectj 使用编译...

  • 通过反射获取spring中aop代理的target对象

    最近项目需要获取从spring创建的aop代理中获取它的target对象,其实可以通过反射来获取,代码如下 aop...

  • Spring AOP(一)

    Spring AOP实现原理 动态代理: 利用核心类Proxy和接口InvocationHandler(基于代理模...

网友评论

      本文标题:获取spring aop 代理目标类

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