昨天晚上一哥们需要获取代理对象的目标对象,查找了文档发现没有相应的工具类,因此自己写了一个分享给大家。能获取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;
} }

在spring中获取代理对象代理的目标对象工具类的更多相关文章

  1. 如何在spring中获取request对象

    1.通过注解获取(很简单,推荐): public class Hello {@Autowired  HttpServletRequest request; //这里可以获取到request} 2.在w ...

  2. spring中获取ApplicationContext对象的技巧,含源码说明

    第一步,实现接口ApplicationContextAware,重写setApplicationContext方法,下方代码标红的地方,绿色部分 可以通过声明来进行存储到本类中. @Component ...

  3. 手动从Spring中获取指定对象

    1.创建ApplicationContext对象: ApplicationContext context = new FileSystemXmlApplicationContext("D:/ ...

  4. Spring中获取被代理的对象

    目录 Spring中获取被代理的对象 获取Spring被代理对象什么时候可能会用到? Spring中获取被代理的对象 Spring中获取被代理的对象 ### 获取Spring被代理对象的JAVA工具类 ...

  5. Spring中的JDK动态代理

    Spring中的JDK动态代理 在JDK1.3以后提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.在Sun刚推出动态代理时,还很难想象它有多大的实际用途,现在动态代理是实现AOP的绝好底层 ...

  6. 获取JDK动态代理/CGLIB代理对象代理的目标对象。

    问题描述:: 我现在遇到个棘手的问题,要通过spring托管的service类保存对象,这个类是通过反射拿到的,经过实验发现这个类只能反射取得sservice实现了接口的方法,而extends类的方法 ...

  7. Spring中的cglib动态代理

    Spring中的cglib动态代理 cglib:Code Generation library, 基于ASM(java字节码操作码)的高性能代码生成包 被许多AOP框架使用 区别于JDK动态代理,cg ...

  8. spring中获取dao或对象中方法的实例化对象

    spring中获取dao的中方法的实例化对象: //获取应用上下文对象 ApplicationContext ctx = new ClassPathXmlApplicationContext(&quo ...

  9. Spring中获取request的几种方法,及其线程安全性分析

    前言 本文将介绍在Spring MVC开发的web系统中,获取request对象的几种方法,并讨论其线程安全性. 原创不易,如果觉得文章对你有帮助,欢迎点赞.评论.文章有疏漏之处,欢迎批评指正. 欢迎 ...

随机推荐

  1. Scala 中的函数式编程基础(一)

    主要来自 Scala 语言发明人 Martin Odersky 教授的 Coursera 课程 <Functional Programming Principles in Scala>. ...

  2. 温故知新---重读C#InDepth(一)

    一本好书,或是一本比较有深度的书,就是每次研读的时候都会有新的发现. 好吧,我承认每次读的时候都有泛泛而过的嫌疑~~ 这几年一直专注于C#客户端的开发,逐步从迷迷糊糊,到一知半解,再到自以为是,最后沉 ...

  3. WEB前端开发规范

    WEB前端开发规范 规范目的 为提高团队协作效率, 便于后台人员添加功能及前端后期优化维护, 输出高质量的文档, 特制订此文档.本文档如有不对或者不合适的地方请及时提出, 经讨论决定后方可更改. 基本 ...

  4. iOS UI基础-17.0 UILable之NSMutableAttributedString

    在iOS开发中,常常会有一段文字显示不同的颜色和字体,或者给某几个文字加删除线或下划线的需求.之前在网上找了一些资料,有的是重绘UILabel的textLayer,有的是用html5实现的,都比较麻烦 ...

  5. json_decode详解

    json_decode是php5.2.0之后新增的一个PHP内置函数,其作用是对JSON 格式的字符串进行编码.    json_decode的语法规则:json_decode ( string $j ...

  6. 复合sql

    update select update bucp..Core_Flow_Opinion set useruid =(select user_uid from bua..bua_user b wher ...

  7. 压缩算法实现之LZ78

    LZ78编码 LZ78算法,建立词典的算法. LZ78的编码思想: 不断地从字符流中提取新的缀-符串(String),通俗地理解为新"词条",然后用"代号"也就 ...

  8. Java异常分类

    一.基本概念 看java的异常结构图 Throwable是所有异常的根,java.lang.ThrowableError是错误,java.lang.ErrorException是异常,java.lan ...

  9. 【前端】less学习

    Less 是什么? Less is more,than CSS. Less就是搞笑高效编写和维护CSS的一种语法. 1.下载Koala考拉,一款国人编写的less开发器. 2.可以用Sublime T ...

  10. 【UVA 1586】Ancient Cipher

    题 题意 给你一个只含CHON的有机物的化学式如C6H5OH求相对分子质量 分析 ... 代码 switch #include<cstdio> #include<cctype> ...