Spring中获取被代理的对象
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;
}
}
效果截图
效果说明: 三个方法效果一样.
System.setProperty("cglib.debugLocation","E:\\data\\spring")
用来指定 代理类class文件生成位置,在CGLIB中也可以这么用。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被代理了之后就进入到了真正的UserService
的 getDao 方法.
提示:代码不规范,同事两行泪,这种写法不太规范仅供出现问题时定位.
Spring中获取被代理的对象的更多相关文章
- spring中获取dao或对象中方法的实例化对象
spring中获取dao的中方法的实例化对象: //获取应用上下文对象 ApplicationContext ctx = new ClassPathXmlApplicationContext(&quo ...
- java 从spring容器中获取注入的bean对象
java 从spring容器中获取注入的bean对象 CreateTime--2018年6月1日10点22分 Author:Marydon 1.使用场景 控制层调用业务层时,控制层需要拿到业务层在 ...
- SpringMvc4中获取request、response对象的方法
springMVC4中获取request和response对象有以下两种简单易用的方法: 1.在control层获取 在control层中获取HttpServletRequest和HttpServle ...
- springMVC中获取request和response对象的几种方式(RequestContextHolder)
springMVC中获取request和response对象的几种方式 1.最简单方式:参数 2.加入监听器,然后在代码里面获取 原文链接:https://blog.csdn.net/weixin_4 ...
- jquery中获取当前点击对象
jquery中获取当前点击对象的简单方法就是,在点击事件click中传入event对象 click(function(event)); 调用当前对象就是$(event.target);
- spring中获取当前项目的真实路径
总结: 方法1: WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext ...
- 在spring中获取代理对象代理的目标对象工具类
昨天晚上一哥们需要获取代理对象的目标对象,查找了文档发现没有相应的工具类,因此自己写了一个分享给大家.能获取JDK动态代理/CGLIB代理对象代理的目标对象. 问题描述:: 我现在遇到个棘手的问题,要 ...
- Spring中获取对象
Spring是一个非常主流,而且是好用的框架.提供管理对象的容器,提供事务的支持,缓存,权限认证(往往不用).用来集成hibernate等.而管理对象的生命周期是其中一个非常重要的功能.在Spring ...
- spring aop获取目标对象的方法对象(包括方法上的注解)
这两天在学习权限控制模块.以前看过传智播客黎活明老师的巴巴运动网视频教程,里面就讲到权限控制的解决方案,当时也只是看看视频,没有动手实践,虽说看过几遍,可是对于系统中的权限控制还是很迷茫,所以借着这次 ...
随机推荐
- SpringBoot入门-集成mybatis(四)
pom.xml <parent> <groupId>org.springframework.boot</groupId> <artifactId>spr ...
- 【GMT43智能液晶模块】例程十六:LAN_TCPS实验——以太网数据传输
源代码下载链接: 链接:https://pan.baidu.com/s/1e5Qp-xASjlA0pje3S7TdIg提取码:9v37 复制这段内容后打开百度网盘手机App,操作更方便哦 GMT43购 ...
- cent os 部署blade
一:安装docker 二:安装docker-compose 三:安装Harbor 四:配置Harbor使用https和2376端口 在/etc/docker 目录下面创建文件:create_tls_c ...
- 【Spring Boot学习之十二】mybatis3 分页打印sql日志
环境 eclipse 4.7 jdk 1.8 Spring Boot 1.5.2 参考: mybatis手册 Mybatis的插件 PageHelper 分页查询使用方法MyBatis中Like语句使 ...
- 无限用teamviewer的一种方法,虚拟机中装teamviewer
可以使用window 多用户可以同时远程登陆的特性(win服务器版自动支持多用户同时远程登陆,非服务器版需要其他方法开启) 1.在window建立两个用户,如a,b. 2安装虚拟机vmware,安装操 ...
- centos7 spark2.3.1集群搭建
1.安装jdk 2.安装scala 参照jdk的安装 3.ssh 免密码登录 4.安装hadoop 以上四步请参照 centos7 安装hadoop2.7.6(分布式) 5.安装spark 1) ...
- OTP详解
OTP(One Time Programmable)是单片机的一种存储器类型,意思是一次性可编程:程序烧入单片机后,将不可再次更改和清除. 随着嵌入式应用的越来越广泛,产品的安全也显得越来越重要.一方 ...
- ThinkPHP3(添加,修改,删除)
实现商品的添加 1.在add.html页面中更改表单元素的名称 Goods控制器的add()方法中获取商品分类 在add.html中循环获取 2.设置提交的位置 3.添加商品代码参见GoodsCont ...
- 搭建kafaka集群
服务器环境准备 使用vm虚拟三个linux主机 192.168.212.174 192.168.212.175 192.168.212.176 Zookeeper集群环境搭建 1.每台服务器节点上安装 ...
- 【转帖】极简Docker和Kubernetes发展史
极简Docker和Kubernetes发展史 https://www.cnblogs.com/chenqionghe/p/11454248.html 2013年 Docker项目开源 2013年,以A ...