Spring中获取被代理的对象

目录

  • Spring中获取被代理的对象

    • 获取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;
    }
}

效果截图

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

  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 方法.

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

原文地址:https://www.cnblogs.com/lvbinbin2yujie/p/11143402.html

时间: 2024-08-20 02:11:21

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

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

spring中获取dao的中方法的实例化对象: 1 //获取应用上下文对象 2 ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml"); 3 //例子:获取dicDao实例 4 dicDao = ctx.getBean(IDicDao.class); //例子2:获取MemcacheAccess的实例: 5 memcachedAccess = ctx.getBean(Memcach

spring中获取applicationContext

常用的5种获取spring 中bean的方式总结: 方法一:在初始化时保存ApplicationContext对象代码:ApplicationContext ac = new FileSystemXmlApplicationContext("applicationContext.xml");ac.getBean("beanId");说明:这种方式适用于采用Spring框架的独立应用程序,需要程序通过配置文件手工初始化Spring的情况. 方法二:通过Spring提供

Spring 中获取 request 的几种方法,及其线程安全性分析

概述在使用Spring MVC开发Web系统时,经常需要在处理请求时使用request对象,比如获取客户端ip地址.请求的url.header中的属性(如cookie.授权信息).body中的数据等.由于在Spring MVC中,处理请求的Controller.Service等对象都是单例的,因此获取request对象时最需要注意的问题,便是request对象是否是线程安全的:当有大量并发请求时,能否保证不同请求/线程中使用不同的request对象.这里还有一个问题需要注意:前面所说的"在处理请

spring中获取applicationContext(2)

前几天写web项目的时候,用到了spring mvc. 但是又写bean.我要在代码里面生成,而这个bean里面,又有一些属性是通过spring注入的. 所以,只能通过ApplicationContext来获取. 在servlet里面获取ApplicationContext其实可以通过spring提供的方法: ? 1 WebApplicationContextUtils.getWebApplicationContext(ServletContext) 来获取. 这个方法前提是要在web.xml里

如何在JSTL中获取数组或者list对象的索引值(index)

<c:forEach items="${productList}" var="products" varStatus="status"> 产品序号:${status.count} 产品名称:${products.name} </c:forEach> 上面代码中的varStatus是关键,${status.count}即是我们要的数组的索引值. 如何在JSTL中获取数组或者list对象的索引值(index)

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

问题描述:: 我现在遇到个棘手的问题,要通过spring托管的service类保存对象,这个类是通过反射拿到的,经过实验发现这个类只能反射取得sservice实现了接口的方法,而extends类的方法一律不出现,debug后发现这个servie实例被spring替换成jdkdynmicproxy类,而不是原始对象了,,它里面只有service继承的接口方法,而没有extends 过的super class方法,怎么调用原生对象的方法!!!!! 用托管的spring service类调用getCl

Spring中自动创建代理器

1.AbstractAutoProxyCreator 该类继承关系如代码所示: public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware { 首先,它继承了ProxyProcessorSupport,查看该类: // 显然,它是个ProxyConfig 拥有AOP

Spring(六) Spring中的静态代理

在Spring中代理有两种一种是静态代理一种是动态代理 这篇博客想讲一下静态代理 首先要知道什么是静态代理(查找了一下其他博客) 了解一下静态代理满足的条件和他的弊端 1.需要知道核心类(被代理类)是哪一个类,并且有什么方法. 2.非核心的代码需要重复写多次,显得代码的结构臃肿,形成代码冗余. 3.非核心类(代理类)需要实现核心类(被代理类)实现的接口,也就是他们需要实现共同的接口,但是以核心类实现的接口(被代理类)为准. 下面通过一个例子来说明 先声明一个主题接口,接口的实现类有两个一个是真实

spring中使用动态代理(AOP)

spring是整合了BGLIB和JDK两种动态代理 示例:使用CGLIB代理 public class MyCar { private String color = "blue"; public void run() { System.out.println("我的汽车跑起来了" + color); } } 测试 public class SpringProxy { public static void main(String[] args) { //将代理类的cl