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. pycharm 生成requirements.txt

    在命令行中输入 pip freeze>requirements.txt 1 安装requirements文件中的包 pip install -r requirements.txt

  2. fiddler抓包详解

    image.png 前言 fiddler是一个很好的抓包工具,默认是抓http请求的,对于pc上的https请求,会提示网页不安全,这时候需要在浏览器上安装证书. 一.网页不安全 1.用fiddler ...

  3. 自动化办公:python操作Excel

    1.安装 -- upgrade pippython -m pip install --- install pypipip install pypi 执行python setup.py install进 ...

  4. php nl2br 将\n变成<br />

    <?php $str="h t m l"; //定义一个多处换行的字串 echo "未处理前的输出形式:<br />{$str}"; #nl2 ...

  5. 更换yum源为阿里云源

    1.复制备份: cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 2.下载: wget -O ...

  6. laydate.render报错:日期格式不合法

    在使用laydate渲染日期时: laydate.render({ elem: '#day' }); 提示日期格式不合法 需要使用 too.dateType()来包装 <input type=& ...

  7. 使用termux在安卓手机上搭建python开发环境

    下载安装termux应用. 应用链接如下:https://download.csdn.net/upload/11342944设置-应用-termux赋予存储权限 cd mkdir .termux vi ...

  8. Windows版的OpenJDK下载(Red Hat 提供)

    OpenJDK 在linux下安装很简单(yum安装),但是OpenJDK的官网没有为我们提供Windows版的安装软件.庆幸的是,Red Hat(红帽)为我们提供了windows版的安装软件. 下载 ...

  9. canal使用

    报错信息:com.alibaba.druid.pool.DruidDataSource - testWhileIdle is true, validationQuery not set 解决方法: 找 ...

  10. spring的exception

    Springmvc的对于异常类进行统一处理的方法 一.局部异常统一处理 当异常出现时,将抛给异常处理方法,异常处理发放接收到异常数据,进行处理,统一到异常页面 @ExceptionHandler:通过 ...