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获取目标对象的方法对象(包括方法上的注解)
这两天在学习权限控制模块.以前看过传智播客黎活明老师的巴巴运动网视频教程,里面就讲到权限控制的解决方案,当时也只是看看视频,没有动手实践,虽说看过几遍,可是对于系统中的权限控制还是很迷茫,所以借着这次 ...
随机推荐
- Python用积分思想计算圆周率
[文本出自天外归云的博客园] 早上起来突然想求圆周率,1单位时圆的面积. 代码如下: from math import pow, sqrt def calc_circle_s_with(r, dy, ...
- 如何学会快速调用API
作为一名苦逼的程序员,在实现各种需求的过程中,总是需要调用各种各样的API,也就是要读各种文档.我们所要做的是弄清楚这些API的参数然后调用即可.说起来非常简单,是实际上却不是这样.现在火爆的机器学习 ...
- 浅入深出ETCD之【简介与命令行使用】
前言 你知道etcd吗?随着k8s的使用广泛之后,etcd被非常多的人所知道,同时又因为它可靠的分布式特性被很多人喜欢.所以,我准备有几篇博文来记录一下,从基本使用到线上部署再到原理分析,做一个系列. ...
- roboware 常见操作和问题
博客参考:https://blog.csdn.net/u013528298/article/details/88052470 1. build中错误位置定位方式 按住“CTRL”键并点击错误提示的链接 ...
- bat文件重命名指定路径下文件
ren "E:\产品\Planning\C1-Planning11\C1-Planning11\target\123" 456 此命令是将文件123重命名为456 注意:456是文 ...
- shell基础知识5-函数
函数的定义 function fname(){ } 或者 function_name(){ } 对于简单的函数,甚至可以是这样做 fname() { statement; } 函数调用 直接写函数名即 ...
- 大数据 -- kafka学习笔记:知识点整理(部分转载)
一 为什么需要消息系统 1.解耦 允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束. 2.冗余 消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险.许多 ...
- NuxtJS实战,一个博客系统
前言 这个项目诞生于17年5月,距今已有两年多了,在这两年期间经历了很多变更,从简单到复杂,又从复杂到简单,并且以后一直会保持这种简单状态.最近迎来了一次更新,因此特意分享一下.虽然只有我一个人使用( ...
- [数据结构 - 第6章] 树之二叉排序树(C语言实现)
一.什么是二叉排序树? 对于普通的顺序存储来说,插入.删除操作很简便,效率高:而这样的表由于无序造成查找的效率很低. 对于有序线性表来说(顺序存储的),查找可用折半.插值.斐波那契等查找算法实现,效率 ...
- idea 添加自定义的todo标签
背景:idea添加自定义的todo标签可以提高开发效率,搞之 在idea定义个人风格的todo IDEA自定义TODO注释 主要分为如下两步 自定义todo标签 settings>Editor& ...