`
jinnianshilongnian
  • 浏览: 21505204 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2418798
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:3008949
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5639578
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:259964
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1597402
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:250249
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5859076
Group-logo
跟我学Nginx+Lua开...
浏览量:702309
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:785274
社区版块
存档分类
最新评论

在spring中获取代理对象代理的目标对象工具类

 
阅读更多

 

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

 

 

问题描述::

 

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

 

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

 

 

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

 

这也是为什么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;
	}
	
}

 

 

19
23
分享到:
评论
18 楼 Pigwen 2012-08-01  
jinnianshilongnian 写道
Pigwen 写道
晕,jdk的代理本身就只能搞接口,你让spring用cglib做代理不就好了啊。。。


嗯,如果是私有的呢

那就要反思下为什么会需要去反射这样的方法了。
你现在这个方案搞得了某个版本的cglib,其他版本的cglib万一又改变动态类名字的规则了喃,更何况还有javassist这些其他的动态代理框架存在?
17 楼 jinnianshilongnian 2012-08-01  
Pigwen 写道
晕,jdk的代理本身就只能搞接口,你让spring用cglib做代理不就好了啊。。。


嗯,如果是私有的呢
16 楼 Pigwen 2012-08-01  
晕,jdk的代理本身就只能搞接口,你让spring用cglib做代理不就好了啊。。。
15 楼 jinnianshilongnian 2012-08-01  
moshowgame 写道
jinnianshilongnian 写道
问题描述::

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

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



因为spring AOP底层用的就是动态代理,实现的时候肯定会变成代理类$proxyXX,用.getClass().getName()也得到的也会是这东西。这是基于动态代理的设计模式吧,或许这就是这种模式的缺点所在。


代理就是这样,代理了访问控制; 而且这里既然代理了,就不应该那么使用,说明设计有问题
14 楼 moshowgame 2012-08-01  
jinnianshilongnian 写道
问题描述::

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

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



因为spring AOP底层用的就是动态代理,实现的时候肯定会变成代理类$proxyXX,用.getClass().getName()也得到的也会是这东西。这是基于动态代理的设计模式吧,或许这就是这种模式的缺点所在。
13 楼 jinnianshilongnian 2012-07-31  
grzrt 写道
jinnianshilongnian 写道
grzrt 写道
jinnianshilongnian 写道
grzrt 写道
楼主spring研究的够深入,佩服

下班了嘛


吃完了,学会习 一会就回宿舍了

这么爱学习,现在研究什么呢


热爱什么呀,只是不会的太多。研究你博客呢。
一些工作中用的东西

呵呵
12 楼 grzrt 2012-07-31  
jinnianshilongnian 写道
grzrt 写道
jinnianshilongnian 写道
grzrt 写道
楼主spring研究的够深入,佩服

下班了嘛


吃完了,学会习 一会就回宿舍了

这么爱学习,现在研究什么呢


热爱什么呀,只是不会的太多。研究你博客呢。
一些工作中用的东西
11 楼 jinnianshilongnian 2012-07-31  
grzrt 写道
jinnianshilongnian 写道
grzrt 写道
楼主spring研究的够深入,佩服

下班了嘛


吃完了,学会习 一会就回宿舍了

这么爱学习,现在研究什么呢
10 楼 grzrt 2012-07-31  
jinnianshilongnian 写道
grzrt 写道
楼主spring研究的够深入,佩服

下班了嘛


吃完了,学会习 一会就回宿舍了
9 楼 jinnianshilongnian 2012-07-31  
grzrt 写道
楼主spring研究的够深入,佩服

下班了嘛
8 楼 jinnianshilongnian 2012-07-31  
grzrt 写道
楼主spring研究的够深入,佩服

还没吃饭? 干嘛呢
7 楼 grzrt 2012-07-31  
楼主spring研究的够深入,佩服
6 楼 jinnianshilongnian 2012-07-31  
mojunbin 写道
很好。呵呵。

有需求 就有解决方案 
5 楼 mojunbin 2012-07-31  
很好。呵呵。
4 楼 jinnianshilongnian 2012-07-31  
kjj 写道
                     

我发上来了,解决你的问题了嘛
3 楼 kjj 2012-07-31  
                     
2 楼 jinnianshilongnian 2012-07-31  
问题描述::

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

用托管的spring service类调用getClass().getName()方法,发现输出都是$proxy43这类东西!!
1 楼 jinnianshilongnian 2012-07-31  
这个大家可以参考Spring事务处理时自我调用的解决方案及一些实现方式的风险这篇文章中的InjectBeanSelfProcessor获取。

或者 在目标对象中直接通过this调用

相关推荐

    jdk代理,cgib代理和spring后处理bean的关系

    `AopTargetUtils`是Spring AOP模块中的一个工具类,它提供了用于处理AOP代理和目标对象的一些实用方法。例如,`AopTargetUtils.getTarget(Object proxy)`方法可以获取到代理对象背后的原始目标对象,这对于在处理...

    spring动态代理

    Spring 动态代理是 Spring 框架中的一个重要特性,它允许我们在运行时自动生成代理对象,以便在方法调用前后执行额外的操作,比如事务管理、AOP(面向切面编程)等。动态代理主要涉及两个核心接口:`java.lang....

    Spring源代码解析(五):Spring_AOP获取Proxy.doc

    本文将深入解析Spring AOP如何获取代理对象,即Proxy。 首先,我们需要理解AOP的核心概念: 1. **Advice**:通知,是切面实际执行的操作。在Spring中,Advice可以是Before、AfterReturning、AfterThrowing以及...

    JDK动态代理 spring aop 的原理

    在Java编程领域,JDK动态代理是实现动态创建代理对象的一种技术,它是Java标准库提供的一种强大工具。Spring AOP(面向切面编程)则是一种流行的应用框架,它利用动态代理来实现对业务代码的切面增强,如日志、事务...

    在自定义spring aop中使用el获取拦截方法的变量值。

    标题中的“在自定义Spring AOP中使用EL获取拦截方法的变量值”指的是在Spring的面向切面编程(AOP)中,通过Expression Language(EL,表达式语言)来访问被拦截方法的局部变量值。这通常涉及到Spring的代理机制、...

    spring boot内置工具类

    在Spring Boot框架中,内置了一些非常实用的工具类,这些工具类可以帮助开发者简化代码,提高开发效率。在本文中,我们将深入探讨其中的一些关键工具类,包括对象、数组、集合处理,文件、资源和IO流操作,以及反射...

    使用代理实现简易的spring aop功能

    在Spring框架中,AOP(面向切面编程)是一种强大的工具,它允许程序员定义横切关注点,如日志、事务管理、权限检查等,并将它们模块化为可重用的切面。在这个例子中,我们将探讨如何使用动态代理来实现一个简单的...

    Spring Aop Advise方法(增强方法) 中获取目标方法的参数

    这篇博客文章“Spring Aop Advise方法(增强方法) 中获取目标方法的参数”可能详细解释了如何在Advise中获取被拦截方法的参数。为了深入理解这个主题,我们需要探讨以下几个关键知识点: 1. **AOP的基本概念**: - ...

    动态代理的方式注册到spring容器

    通过这种方式,Spring容器中的`userService` bean将是动态代理对象,当调用其方法时,会先执行我们在`invoke()`方法中定义的逻辑,包括服务降级处理和注解信息的获取。 总结来说,动态代理在Spring中提供了灵活的...

    Java动态代理(Spring Aop原理)

    - 调用Spring容器获取代理对象,执行业务方法时,相应的通知方法会被自动插入。 通过Java动态代理和Spring AOP,开发者能够轻松地实现代码的解耦,提高可维护性和复用性。在实际开发中,理解这些原理并合理运用,...

    Spring aop 基于schema的AOP支持及JoinPoint的使用、如何使用CGLIB代理

    Spring AOP在默认情况下,对于没有实现接口的类,会使用CGLIB库生成代理对象。CGLIB是一个强大的代码生成库,可以在运行时动态生成子类,从而实现对目标对象的代理。 1. **CGLIB工作原理** - CGLIB通过继承目标类...

    [#0x0042] Spring AOP学习(二):动态代理

    2. **获取代理接口**:代理对象需要实现与目标对象相同的接口,因此需要明确这些接口。 3. **生成代理类**:使用Proxy.newProxyInstance()方法,传入代理接口的类加载器、接口数组以及自定义的InvocationHandler,...

    java代理模式

    5. 使用Proxy.newProxyInstance()方法(动态代理)或直接创建代理类的实例(静态代理)来获取代理对象,并通过代理对象调用接口方法。 代理模式在Java开发中有着广泛的应用,比如在AOP(面向切面编程)中,Spring...

    使用Spring降低类之间的耦合

    3. **AOP代理**:Spring可以创建代理对象来拦截方法调用,这不仅支持AOP,还能在不修改原有类的基础上添加额外的行为。 4. **事件驱动**:Spring的ApplicationEvent和ApplicationListener机制允许组件之间通过发布和...

    Spring AOP的底层实现技术

    当我们通过Spring容器获取一个bean时,实际上是获取了它的代理对象。代理对象在调用目标方法前后,会根据通知类型执行相应的逻辑。比如,如果定义了一个前置通知,那么在调用目标方法之前,前置通知会被执行。 6. ...

    Java 动态代理详解(代理模式+静态代理+JDK动态代理+CGLIB动态代理)

    Java 动态代理是 Java 编程语言中的一种强大工具,广泛应用于 Spring AOP、Hibernate 数据查询、测试框架的后端 mock、RPC 远程调用、Java 注解对象获取、日志、用户鉴权、全局性异常处理、性能监控等领域。...

    spring-aop源码解读

    ProxyFactoryBean是Spring AOP用于创建代理对象的主要工具,它实现了BeanFactoryAware、BeanClassLoaderAware和FactoryBean接口,使其能够利用IOC容器的功能来查找并应用Advice和目标对象。 配置和使用...

    Spring-Reference_zh_CN(Spring中文参考手册)

    6.8.1. 在Spring中使用AspectJ来为domain object进行依赖注入 6.8.1.1. @Configurable object的单元测试 6.8.1.2. 多application context情况下的处理 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来...

Global site tag (gtag.js) - Google Analytics