当前位置: 首页 > news >正文

永嘉哪里有做网站亚马逊官网中国网页版

永嘉哪里有做网站,亚马逊官网中国网页版,php双语网站源码,浙江网商银行电话CodingTechWork 引言 在使用 Spring AOP(面向切面编程)时,我们经常会遇到一个棘手的问题:在代理对象上调用某些方法时,无法获取到目标类上的注解。这是因为 Spring 的代理机制会创建一个代理对象,而这个代…

CodingTechWork

引言

  在使用 Spring AOP(面向切面编程)时,我们经常会遇到一个棘手的问题:在代理对象上调用某些方法时,无法获取到目标类上的注解。这是因为 Spring 的代理机制会创建一个代理对象,而这个代理对象可能并不直接继承目标类的注解。本文将通过 AopProxyUtils.ultimateTargetClass() 方法,深入探讨如何解决这一问题,并提供一个完整的解决方案。

问题背景

在 Spring AOP 中,代理对象的创建方式主要有两种:

  • JDK 动态代理:基于接口实现的代理。
  • CGLIB 代理:基于子类实现的代理。

无论是哪种代理方式,代理对象都可能无法直接继承目标类的注解。例如,假设我们有一个目标类 MyService,它有一个注解 @MyCustomAnnotation

@MyCustomAnnotation
public class MyService {public void doSomething() {// 方法实现}
}

当我们通过 Spring AOP 创建代理对象时,直接调用代理对象的 getClass() 方法,可能会得到一个代理类,而不是目标类 MyService。因此,直接在代理对象上调用 getClass().getAnnotation(MyCustomAnnotation.class) 时,可能会返回 null,导致无法获取到目标类上的注解。

问题演示

定义注解

首先,我们定义一个自定义注解 @MyCustomAnnotation

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyCustomAnnotation {
}

定义目标类

然后,我们定义一个目标类 MyService,并在其上添加 @MyCustomAnnotation 注解:

@MyCustomAnnotation
public class MyService {public void doSomething() {System.out.println("Doing something...");}
}

定义配置类

接下来,我们定义一个 Spring 配置类,用于创建 MyService 的 Bean:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Beanpublic MyService myService() {return new MyService();}
}

测试代码

最后,我们编写测试代码,尝试获取代理对象上的注解:

import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class AnnotationProblemDemo {public static void main(String[] args) {// 创建 Spring 应用上下文AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);// 获取代理对象MyService proxy = context.getBean(MyService.class);// 尝试获取注解MyCustomAnnotation annotation = proxy.getClass().getAnnotation(MyCustomAnnotation.class);// 检查注解是否存在if (annotation != null) {System.out.println("注解存在: " + annotation);} else {System.out.println("注解不存在");}// 关闭上下文context.close();}
}

输出结果

运行上述代码,输出结果如下:

Doing something...
注解不存在

可以看到,直接在代理对象上调用 getClass().getAnnotation(MyCustomAnnotation.class) 时,返回了 null,导致无法获取到目标类上的注解。

解决方案:AopProxyUtils.ultimateTargetClass()

为了解决这个问题,Spring 提供了一个非常有用的工具类 AopProxyUtils,其中的 ultimateTargetClass() 方法可以穿透所有代理层,直接获取到最终的目标类。牛不牛!这样,我们就可以通过目标类来获取注解,而不是通过代理类。

方法介绍

AopProxyUtils.ultimateTargetClass() 方法的签名如下:

public static Class<?> ultimateTargetClass(Object proxy)

这个方法接受一个代理对象作为参数,返回最终目标类的 Class 对象。它会穿透所有代理层,直到找到最终的目标类。

修改后的测试代码

我们修改测试代码,使用 AopProxyUtils.ultimateTargetClass() 方法获取最终目标类,并通过目标类来获取注解:

import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class AnnotationSolutionDemo {public static void main(String[] args) {// 创建 Spring 应用上下文AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);// 获取代理对象MyService proxy = context.getBean(MyService.class);// 获取最终目标类Class<?> targetClass = AopProxyUtils.ultimateTargetClass(proxy);// 获取目标类上的注解MyCustomAnnotation annotation = targetClass.getAnnotation(MyCustomAnnotation.class);// 检查注解是否存在if (annotation != null) {System.out.println("注解存在: " + annotation);} else {System.out.println("注解不存在");}// 关闭上下文context.close();}
}

输出结果

运行修改后的代码,输出结果如下:

Doing something...
注解存在: @MyCustomAnnotation()

可以看到,通过 AopProxyUtils.ultimateTargetClass() 方法,我们成功获取到了目标类 MyService 上的注解 @MyCustomAnnotation

深入理解 AopProxyUtils.ultimateTargetClass()

实现原理

AopProxyUtils.ultimateTargetClass() 方法的实现基于 Spring AOP 的内部机制。它会递归地检查代理对象的类层次结构,直到找到最终的目标类。具体来说,它会通过以下步骤实现:

  1. 检查代理对象是否为 AOP 代理:通过 AopUtils.isAopProxy() 方法判断当前对象是否为 AOP 代理对象。
  2. 获取目标类:如果当前对象是 AOP 代理对象,通过 AopProxyUtils.ultimateTargetClass() 方法递归地获取最终的目标类。
  3. 返回目标类:最终返回目标类的 Class 对象。

源码分析

以下是 AopProxyUtils.ultimateTargetClass() 方法的源码:

public static Class<?> ultimateTargetClass(Object candidate) {// 确保传入的对象不为 nullAssert.notNull(candidate, "Candidate object must not be null");Object current = candidate;Class<?> result;// 遍历代理链,直到找到最终的目标类for (result = null; current instanceof TargetClassAware; current = getSingletonTarget(current)) {// 当前对象实现了 TargetClassAware 接口,表示它知道自己的目标类TargetClassAware targetClassAware = (TargetClassAware) current;// 获取目标类result = targetClassAware.getTargetClass();}// 如果没有找到目标类if (result == null) {// 如果当前对象是 CGLIB 代理对象,获取其父类(即目标类)if (AopUtils.isCglibProxy(candidate)) {result = candidate.getClass().getSuperclass();} else {// 否则直接返回当前对象的类result = candidate.getClass();}}// 返回最终的目标类return result;
}

注意事项

  • 依赖 Spring AOPAopProxyUtils 是 Spring AOP 模块的一部分,因此需要在项目中引入 Spring AOP 相关依赖。
  • 代理对象:只有代理对象才能使用 AopProxyUtils.ultimateTargetClass(),如果直接传入一个普通对象,可能会抛出异常或返回错误结果。
  • 性能影响:虽然 AopProxyUtils.ultimateTargetClass() 的实现相对高效,但在高并发场景下,频繁调用可能会对性能产生一定影响,建议合理使用。

总结

在 Spring AOP 中,代理对象的注解获取问题是一个常见的问题。通过 AopProxyUtils.ultimateTargetClass() 方法,我们可以轻松地穿透代理层,获取到最终目标类,并通过目标类来获取注解。这种方法不仅简单高效,而且避免了直接操作代理对象带来的复杂性和不确定性。

http://www.dtcms.com/a/595170.html

相关文章:

  • 网站产品页面目前会展相关网站的建设情况
  • 天河商城网站建设中企动力常州分公司
  • Rust底层深度探究:自定义分配器(Allocators)——控制内存分配的精妙艺术
  • 商城网站开发教程应用软件有哪些系统
  • 南京科技网站设计有特点青岛网站设计工作室
  • 封开网站建设wordpress主题下载失败
  • php 微信 网站开发互联网企业网站
  • 建设一个招聘网站的策划网站建设課程
  • 郑州模板建站代理三亚凤凰镇网站建设兼职招聘网
  • 建一个网站大概需要多少钱舟山市建设信息港网站打不开
  • 求职网站怎么做安徽省安徽省建设工程信息网站
  • 建设新闻博客类网站要多大空间年度考核表个人总结网站建设
  • 学校网站建设都是谁做的no.7极简wordpress博客主题
  • 初创公司网站设计苏州上海高玩seo
  • 金华官方网站建设百度指数网址
  • 长沙网站推广和优化网站开发语言用什么好
  • 专业网站建设集团crm客户管理系统源码
  • 电商网站有哪些类型flash 如何做游戏下载网站
  • 网格系统网站微信小程序平台入口
  • 乐清网站推广做美食视频的网站
  • 东莞网络营销价格咨询怎么对一个网站做优化
  • 北仑建网站价格宿迁网站建设公司
  • 做网站与做网页的区别网站标准宽度
  • 阳泉网站建设哪家便宜学做沪江网站要多久
  • 常用的网站建设程序有那些网站开发软件d
  • 打工人日报#20251110
  • 做手机网站多少钱思科网站建设配置站点dns服务
  • 双语网站建设网站网站建设公司每年可以做多少个网站
  • 网站后台模板 jquery现在的网站开发都用什么开发
  • 果洛州wap网站建设公司手机上如何设置wordpress