通过spring容器中的代理对象获取目标对象
一般情况下,在springboot项目中被IOC容器管理的类在创建对象时,会经过aop的后置处理器(BeanPostProcessor)生成代理对象供我们使用,那如果想要获取目标对象怎么做呢,通常用到AopUtils工具类```public Object test(Object proxy) throws Exception {//判断是否是代理对象if(AopUtils.isAopProxy(p
一般情况下,在springboot项目中被IOC容器管理的类在创建对象时,会经过aop的后置处理器(BeanPostProcessor)生成代理对象供我们使用,那如果想要获取目标对象怎么做呢,通常用到AopUtils工具类```
public Object test(Object proxy) throws Exception {
//判断是否是代理对象
if(AopUtils.isAopProxy(proxy)){
//cglib 代理
if(AopUtils.isCglibProxy(proxy)){
//通过暴力反射拿到代理对象的拦截器属性,从拦截器获取目标对象
Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
h.setAccessible(true);
Object dynamicAdvisedInterceptor = h.get(proxy);
Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
advised.setAccessible(true);
Object target = ((AdvisedSupport)advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();
//返回目标对象
return target;
}
//jdk代理
if(AopUtils.isJdkDynamicProxy(proxy)){
//通过暴力反射拿到代理对象的拦截器属性,从拦截器获取目标对象
Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
h.setAccessible(true);
AopProxy aopProxy = (AopProxy) h.get(proxy);
Field advised = aopProxy.getClass().getDeclaredField("advised");
advised.setAccessible(true);
Object target = ((AdvisedSupport)advised.get(aopProxy)).getTargetSource().getTarget();
return target;
}
}
return null;
}
```
但是,这样做有一个前提,就是aop的后置处理器起作用生成了代理对象。
如果,我想获取某个@Configuration注解的配置类对象的原生目标对象怎么办,上述方法还管用吗?我最近就遇到过这个问题,要通过某个配置类的class通过反射拿到其某个属性,于是按照上述步骤运行,结果大跌眼镜,AopUtils.isAopProxy(proxy)的值居然是false,也就有了我上面标黑的叙述。
已知@Configuration注解的配置类是cglib代理对象,但是却不是aop后置处理器生成的,那么,他的代理对象是怎么生成的?首先,cglib代理是用ASM字节码技术对class文件修改进而完成对目标类的增强的,所以只需要知道配置类的lass文件何处被修改或者替换的。就在spring启动流程中的:
这里,会解析所有配置类,并把class替换成代理类的class,后来getBean获取对象用的就是代理类的class了。具体的代码位置是在ConfigurationClassPostProcessor#enhanceConfigurationClasses
更多推荐
所有评论(0)