獲取spring aop 代理目標類

工作中過程中需要使用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;
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章