昨天晚上一哥们需要获取代理对象的目标对象,查找了文档发现没有相应的工具类,因此自己写了一个分享给大家。能获取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; } }
相关推荐
`AopTargetUtils`是Spring AOP模块中的一个工具类,它提供了用于处理AOP代理和目标对象的一些实用方法。例如,`AopTargetUtils.getTarget(Object proxy)`方法可以获取到代理对象背后的原始目标对象,这对于在处理...
Spring 动态代理是 Spring 框架中的一个重要特性,它允许我们在运行时自动生成代理对象,以便在方法调用前后执行额外的操作,比如事务管理、AOP(面向切面编程)等。动态代理主要涉及两个核心接口:`java.lang....
本文将深入解析Spring AOP如何获取代理对象,即Proxy。 首先,我们需要理解AOP的核心概念: 1. **Advice**:通知,是切面实际执行的操作。在Spring中,Advice可以是Before、AfterReturning、AfterThrowing以及...
在Java编程领域,JDK动态代理是实现动态创建代理对象的一种技术,它是Java标准库提供的一种强大工具。Spring AOP(面向切面编程)则是一种流行的应用框架,它利用动态代理来实现对业务代码的切面增强,如日志、事务...
标题中的“在自定义Spring AOP中使用EL获取拦截方法的变量值”指的是在Spring的面向切面编程(AOP)中,通过Expression Language(EL,表达式语言)来访问被拦截方法的局部变量值。这通常涉及到Spring的代理机制、...
在Spring Boot框架中,内置了一些非常实用的工具类,这些工具类可以帮助开发者简化代码,提高开发效率。在本文中,我们将深入探讨其中的一些关键工具类,包括对象、数组、集合处理,文件、资源和IO流操作,以及反射...
在Spring框架中,AOP(面向切面编程)是一种强大的工具,它允许程序员定义横切关注点,如日志、事务管理、权限检查等,并将它们模块化为可重用的切面。在这个例子中,我们将探讨如何使用动态代理来实现一个简单的...
这篇博客文章“Spring Aop Advise方法(增强方法) 中获取目标方法的参数”可能详细解释了如何在Advise中获取被拦截方法的参数。为了深入理解这个主题,我们需要探讨以下几个关键知识点: 1. **AOP的基本概念**: - ...
通过这种方式,Spring容器中的`userService` bean将是动态代理对象,当调用其方法时,会先执行我们在`invoke()`方法中定义的逻辑,包括服务降级处理和注解信息的获取。 总结来说,动态代理在Spring中提供了灵活的...
- 调用Spring容器获取代理对象,执行业务方法时,相应的通知方法会被自动插入。 通过Java动态代理和Spring AOP,开发者能够轻松地实现代码的解耦,提高可维护性和复用性。在实际开发中,理解这些原理并合理运用,...
Spring AOP在默认情况下,对于没有实现接口的类,会使用CGLIB库生成代理对象。CGLIB是一个强大的代码生成库,可以在运行时动态生成子类,从而实现对目标对象的代理。 1. **CGLIB工作原理** - CGLIB通过继承目标类...
2. **获取代理接口**:代理对象需要实现与目标对象相同的接口,因此需要明确这些接口。 3. **生成代理类**:使用Proxy.newProxyInstance()方法,传入代理接口的类加载器、接口数组以及自定义的InvocationHandler,...
5. 使用Proxy.newProxyInstance()方法(动态代理)或直接创建代理类的实例(静态代理)来获取代理对象,并通过代理对象调用接口方法。 代理模式在Java开发中有着广泛的应用,比如在AOP(面向切面编程)中,Spring...
3. **AOP代理**:Spring可以创建代理对象来拦截方法调用,这不仅支持AOP,还能在不修改原有类的基础上添加额外的行为。 4. **事件驱动**:Spring的ApplicationEvent和ApplicationListener机制允许组件之间通过发布和...
当我们通过Spring容器获取一个bean时,实际上是获取了它的代理对象。代理对象在调用目标方法前后,会根据通知类型执行相应的逻辑。比如,如果定义了一个前置通知,那么在调用目标方法之前,前置通知会被执行。 6. ...
Java 动态代理是 Java 编程语言中的一种强大工具,广泛应用于 Spring AOP、Hibernate 数据查询、测试框架的后端 mock、RPC 远程调用、Java 注解对象获取、日志、用户鉴权、全局性异常处理、性能监控等领域。...
ProxyFactoryBean是Spring AOP用于创建代理对象的主要工具,它实现了BeanFactoryAware、BeanClassLoaderAware和FactoryBean接口,使其能够利用IOC容器的功能来查找并应用Advice和目标对象。 配置和使用...
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来...