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. SpringBoot入门-集成mybatis(四)

    pom.xml <parent> <groupId>org.springframework.boot</groupId> <artifactId>spr ...

  2. 【GMT43智能液晶模块】例程十六:LAN_TCPS实验——以太网数据传输

    源代码下载链接: 链接:https://pan.baidu.com/s/1e5Qp-xASjlA0pje3S7TdIg提取码:9v37 复制这段内容后打开百度网盘手机App,操作更方便哦 GMT43购 ...

  3. cent os 部署blade

    一:安装docker 二:安装docker-compose 三:安装Harbor 四:配置Harbor使用https和2376端口 在/etc/docker 目录下面创建文件:create_tls_c ...

  4. 【Spring Boot学习之十二】mybatis3 分页打印sql日志

    环境 eclipse 4.7 jdk 1.8 Spring Boot 1.5.2 参考: mybatis手册 Mybatis的插件 PageHelper 分页查询使用方法MyBatis中Like语句使 ...

  5. 无限用teamviewer的一种方法,虚拟机中装teamviewer

    可以使用window 多用户可以同时远程登陆的特性(win服务器版自动支持多用户同时远程登陆,非服务器版需要其他方法开启) 1.在window建立两个用户,如a,b. 2安装虚拟机vmware,安装操 ...

  6. centos7 spark2.3.1集群搭建

    1.安装jdk 2.安装scala 参照jdk的安装 3.ssh 免密码登录 4.安装hadoop 以上四步请参照   centos7 安装hadoop2.7.6(分布式) 5.安装spark  1) ...

  7. OTP详解

    OTP(One Time Programmable)是单片机的一种存储器类型,意思是一次性可编程:程序烧入单片机后,将不可再次更改和清除. 随着嵌入式应用的越来越广泛,产品的安全也显得越来越重要.一方 ...

  8. ThinkPHP3(添加,修改,删除)

    实现商品的添加 1.在add.html页面中更改表单元素的名称 Goods控制器的add()方法中获取商品分类 在add.html中循环获取 2.设置提交的位置 3.添加商品代码参见GoodsCont ...

  9. 搭建kafaka集群

    服务器环境准备 使用vm虚拟三个linux主机 192.168.212.174 192.168.212.175 192.168.212.176 Zookeeper集群环境搭建 1.每台服务器节点上安装 ...

  10. 【转帖】极简Docker和Kubernetes发展史

    极简Docker和Kubernetes发展史 https://www.cnblogs.com/chenqionghe/p/11454248.html 2013年 Docker项目开源 2013年,以A ...