zoukankan      html  css  js  c++  java
  • 在spring中获取代理对象代理的目标对象工具类

    昨天晚上一哥们需要获取代理对象的目标对象,查找了文档发现没有相应的工具类,因此自己写了一个分享给大家。能获取JDK动态代理/CGLIB代理对象代理的目标对象。

    问题描述::

    我现在遇到个棘手的问题,要通过spring托管的service类保存对象,这个类是通过反射拿到的,经过实验发现这个类只能反射取得sservice实现了接口的方法,而extends类的方法一律不出现,debug后发现这个servie实例被spring替换成jdkdynmicproxy类,而不是原始对象了,,它里面只有service继承的接口方法,而没有extends 过的super class方法,怎么调用原生对象的方法!!!!!

    用托管的spring service类调用getClass().getName()方法,发现输出都是$proxy43这类东西!!

    通过此种方式获取目标对象是不可靠的,或者说任何获取目标对象的方式都是不可靠的,因为TargetSource,TargetSource中存放了目标对象,但TargetSource有很多种实现,默认我们使用的是SingletonTargetSource ,但还有其他的比如ThreadLocalTargetSource、CommonsPoolTargetSource 等等。

    这也是为什么spring没有提供获取目标对象的API。

    import java.lang.reflect.Field;  
      
    import org.springframework.aop.framework.AdvisedSupport;  
    import org.springframework.aop.framework.AopProxy;  
    import org.springframework.aop.support.AopUtils;  
      
    public class AopTargetUtils {  
      
          
        /** 
         * 获取 目标对象 
         * @param proxy 代理对象 
         * @return  
         * @throws Exception 
         */  
        public static Object getTarget(Object proxy) throws Exception {  
              
            if(!AopUtils.isAopProxy(proxy)) {  
                return proxy;//不是代理对象  
            }  
              
            if(AopUtils.isJdkDynamicProxy(proxy)) {  
                return getJdkDynamicProxyTargetObject(proxy);  
            } else { //cglib  
                return getCglibProxyTargetObject(proxy);  
            }  
              
              
              
        }  
      
      
        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();  
              
            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();  
              
            return target;  
        }  
          
    }  
  • 相关阅读:
    使用 Dockerfile 定制镜像
    UVA 10298 Power Strings 字符串的幂(KMP,最小循环节)
    UVA 11090 Going in Cycle!! 环平均权值(bellman-ford,spfa,二分)
    LeetCode Best Time to Buy and Sell Stock 买卖股票的最佳时机 (DP)
    LeetCode Number of Islands 岛的数量(DFS,BFS)
    LeetCode Triangle 三角形(最短路)
    LeetCode Swap Nodes in Pairs 交换结点对(单链表)
    LeetCode Find Minimum in Rotated Sorted Array 旋转序列找最小值(二分查找)
    HDU 5312 Sequence (规律题)
    LeetCode Letter Combinations of a Phone Number 电话号码组合
  • 原文地址:https://www.cnblogs.com/damowang/p/4172733.html
Copyright © 2011-2022 走看看