Spring中获取被代理的对象

Spring中获取被代理的对象

获取Spring被代理对象的JAVA工具类

​ Spring采用CGLIB或者JDK动态代理来实现AOP,那如何获取 被代理对象?通过ApplicationContext.getBean()获取到的对象都是 利用字节码动态生成的 增强对象,那假如我们有场景获取 被代理的对象,方式如下: (封装到工具类形式里面,直接通过getTrueTargetFrom0即可调用,需要强转一下类型.)

import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.cglib.proxy.MethodInterceptor; import java.lang.reflect.Field; public class SpringUtils { public static Object getTrueTargetFrom0(Object obj){
try {
//获取第一个拦截器
Field field = obj.getClass().getDeclaredField("CGLIB$CALLBACK_0");
field.setAccessible(true);
MethodInterceptor interceptor = (MethodInterceptor) field.get(obj); //获取拦截器的属性advised
Field advised = interceptor.getClass().getDeclaredField("advised");
advised.setAccessible(true);
AdvisedSupport advisedSupport = (AdvisedSupport) advised.get(interceptor);
TargetSource targetSource=null;
if (advisedSupport!=null) {
targetSource = advisedSupport.getTargetSource();
}
return targetSource!=null?targetSource.getTarget():null;
} catch (Exception e) {
e.printStackTrace();
}
return null;
} public static Object getTrueTargetFrom1(Object obj){
try {
//获取第二个拦截器
Field field = obj.getClass().getDeclaredField("CGLIB$CALLBACK_1");
field.setAccessible(true);
MethodInterceptor interceptor = (MethodInterceptor) field.get(obj); //获取拦截器的属性advised
Field advised = interceptor.getClass().getDeclaredField("target");
advised.setAccessible(true);
Object result = advised.get(interceptor);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
} public static Object getTrueTargetFrom3(Object obj){
try {
//获取第四个拦截器
Field field = obj.getClass().getDeclaredField("CGLIB$CALLBACK_3");
field.setAccessible(true);
MethodInterceptor interceptor = (MethodInterceptor) field.get(obj); //获取拦截器的属性advised
Field advised = interceptor.getClass().getDeclaredField("target");
advised.setAccessible(true);
Object result = advised.get(interceptor);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

效果截图

​ 效果说明: 三个方法效果一样.

  1. System.setProperty("cglib.debugLocation","E:\\data\\spring")用来指定 代理类class文件生成位置,在CGLIB中也可以这么用。
  2. getTrueTargetFrom0等方法是如何获取被代理对象UserService的,有一定CGLIB基础之后,代理类中存在回调类,属性CGLIB$CALLBACK_x(x 为数字),Spring生成 代理类时候会将 被代理的UserService保存起来在某些CGLIB$CALLBACK_x中. 这些需要查看源码才能有个轮廓的了解。

获取Spring被代理对象什么时候可能会用到?

​ CGLIB代理是基于继承或者实现接口的方式,我们可能只需要知道 class 属性就能生成代理类,这样做带来的问题:

父类(被代理类)的属性可能我们 只能通过 方法 来获取,比如有个dao属性,不是private修饰类型的,我们不想通过getDao来获取,想直接调用 属性 ,那可能就是空的. 下面看下例子,

@Service
public class UserService {
@Autowired
public UserDao dao; public void addUser(){
System.out.println("添加用户");
} public UserDao getDao() {
return dao;
}
}

这样一个类可能不符合代码编写,但是用来介绍实验效果够了。 比如我们 ApplicationContext.getBean(UserService.class).getDao是能够获取到注入的DAO,但是ApplicationContext.getBean(UserService.class).dao输出的就是null. 原因很简单,CGLIB增强的是方法,dao肯定就是空的,getDao被代理了之后就进入到了真正的UserServicegetDao 方法.

​ 提示:代码不规范,同事两行泪,这种写法不太规范仅供出现问题时定位.

Spring中获取被代理的对象的更多相关文章

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

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

  2. java 从spring容器中获取注入的bean对象

      java 从spring容器中获取注入的bean对象 CreateTime--2018年6月1日10点22分 Author:Marydon 1.使用场景 控制层调用业务层时,控制层需要拿到业务层在 ...

  3. SpringMvc4中获取request、response对象的方法

    springMVC4中获取request和response对象有以下两种简单易用的方法: 1.在control层获取 在control层中获取HttpServletRequest和HttpServle ...

  4. springMVC中获取request和response对象的几种方式(RequestContextHolder)

    springMVC中获取request和response对象的几种方式 1.最简单方式:参数 2.加入监听器,然后在代码里面获取 原文链接:https://blog.csdn.net/weixin_4 ...

  5. jquery中获取当前点击对象

    jquery中获取当前点击对象的简单方法就是,在点击事件click中传入event对象 click(function(event)); 调用当前对象就是$(event.target);

  6. spring中获取当前项目的真实路径

    总结: 方法1: WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext ...

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

    昨天晚上一哥们需要获取代理对象的目标对象,查找了文档发现没有相应的工具类,因此自己写了一个分享给大家.能获取JDK动态代理/CGLIB代理对象代理的目标对象. 问题描述:: 我现在遇到个棘手的问题,要 ...

  8. Spring中获取对象

    Spring是一个非常主流,而且是好用的框架.提供管理对象的容器,提供事务的支持,缓存,权限认证(往往不用).用来集成hibernate等.而管理对象的生命周期是其中一个非常重要的功能.在Spring ...

  9. spring aop获取目标对象的方法对象(包括方法上的注解)

    这两天在学习权限控制模块.以前看过传智播客黎活明老师的巴巴运动网视频教程,里面就讲到权限控制的解决方案,当时也只是看看视频,没有动手实践,虽说看过几遍,可是对于系统中的权限控制还是很迷茫,所以借着这次 ...

随机推荐

  1. 【GM4008】GM4008升级固件发布(版本V4.2.1.1)

    ===================== GM4008固件升级发布 ===================== 〇.简介:GM4008 8通道0-24mA电流采集模块,采用全电气隔离方案,配合高性能 ...

  2. (原)关于OpenGL中的几个坐标系统的理解

    在我们使用opengl做图像处理的过程中,其中必不可少的基本都会用到顶点着色器和片元着色器. 完整的渲染管线图: 那么在这两个着色器程序中,我们需要绘制我们的图像的时候,他们的坐标和位置对应关系是如何 ...

  3. matlab学习笔记13_3创建函数句柄

    一起来学matlab-matlab学习笔记13函数 13_3 创建函数句柄 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 https://ww2.mathworks.cn/help ...

  4. WEB程序设计 第7版

    WEB程序设计 第7版   D11章基础知识1.1internet简介1.1.1起源1.1.2internet的含义1.1.3ip地址1.1.4域名1.2万维网1.2.1起源1.2.2web还是int ...

  5. Spring MVC -- 下载文件

    像图片或者HTML文件这样的静态资源,在浏览器中打开正确的URL即可下载,只要该资源是放在应用程序的目录下,或者放在应用程序目录的子目录下,而不是放在WEB-INF下,tomcat服务器就会将该资源发 ...

  6. javascript Round Function

    var rounded = Math.round( number * 10 ) / 10; // round to one digit var rounded = Math.round( number ...

  7. WebDriver常用的api

    WebDriver常用的api 获取window对象 Window window = driver.manage().window(); 1)  窗口最大化 Maximize() 2)  窗口大小 g ...

  8. dd命令的使用

    1.dd命令的使用 dd命令用于复制文件并对源文件的内容进行转换和格式化处理,在有需要的时候可以使用dd命令对物理磁盘进行操作,使用dd对磁盘操作时,最好使用块设备文件. (1)命令语法 dd (选项 ...

  9. 深入分析——HashSet是否真的无序?(JDK8)

    HashSet 是否无序 (一) 问题起因: <Core Java Volume I-Fundamentals>中对HashSet的描述是这样的: HashSet:一种没有重复元素的无序集 ...

  10. Python3 - 数字类型

    在 Python 中,数字并不是一个真正的对象类型,而是一组类似类型的分类.Python 不仅支持通常的数字类型(整数和浮点数),而且还能够通过常量去直接创建数字以及处理数字的表达式.数字数据类型是不 ...