使用自定义注解和切面AOP实现Java程序增强 (2)

这个注解也没有任何取值,能修饰所有的类型,永久存在。这个注解的作用是,告诉使用者被修饰的代码不推荐使用了,可能会在下一个软件版本中移除。这个注解仅仅起到一个通知机制,如果代码调用了被@Deprecated 修饰的代码,编译器在编译时输出一个编译告警。

1.4.3 @SuppressWarnings

@SuppressWarnings它的定义为:

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE) public @interface SuppressWarnings { /** * The set of warnings that are to be suppressed by the compiler in the * annotated element. Duplicate names are permitted. The second and * successive occurrences of a name are ignored. The presence of * unrecognized warning names is <i>not</i> an error: Compilers must * ignore any warning names they do not recognize. They are, however, * free to emit a warning if an annotation contains an unrecognized * warning name. * * <p> The string {@code "unchecked"} is used to suppress * unchecked warnings. Compiler vendors should document the * additional warning names they support in conjunction with this * annotation type. They are encouraged to cooperate to ensure * that the same names work across multiple compilers. * @return the set of warnings to be suppressed */ String[] value(); }

这个注解有一个字符串数组的值,需要我们使用注解的时候传递。可以在类型、属性、方法、参数、构造函数和局部变量前使用,声明周期是编译期。

这个注解的主要作用是压制编译告警的。

2.AOP介绍(AspectJ暂不讨论) 2.1 Spring AOP基本概念

是一种动态编译期增强性AOP的实现

与IOC进行整合,不是全面的切面框架

与动态代理相辅相成

有两种实现:基于jdk动态代理、cglib

2.2 Spring AOP与AspectJ区别

Spring的AOP是基于动态代理的,动态增强目标对象,而AspectJ是静态编译时增强,需要使用自己的编译器来编译,还需要织入器

使用AspectJ编写的java代码无法直接使用javac编译,必须使用AspectJ增强的ajc增强编译器才可以通过编译,写法不符合原生Java的语法;而Spring AOP是符合Java语法的,也不需要指定编译器去编译,一切都由Spring 处理。

2.3 使用步骤

定义业务组件

定义切点(重点)

定义增强处理方法(切面方法)

这边用下面例子的AOP类来进行说明 (基于Spring AOP的)

/** * @Author Song * @Date 2020/5/26 9:50 * @Version 1.0 */ @Slf4j @Aspect @Component public class EagleEyeAspect { @Pointcut("@annotation(com.ctgu.song.plantfactory.v2.annotation.EagleEye)") public void eagleEye() { } @Around("eagleEye()") public Object around(ProceedingJoinPoint pjp) throws Throwable { long begin = System.currentTimeMillis(); ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); Signature signature = pjp.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; Method method = methodSignature.getMethod(); EagleEye eagleEye = method.getAnnotation(EagleEye.class); String desc = eagleEye.desc(); log.info("============请求开始=========="); log.info("请求链接:{}", request.getRequestURI().toString()); log.info("接口描述:{}", desc); log.info("请求类型:{}", request.getMethod()); log.info("请求方法:{}.{}", signature.getDeclaringTypeName(), signature.getName()); log.info("请求IP:{}", request.getRemoteAddr()); log.info("请求入参:{}", JSON.toJSONString(pjp.getArgs())); Object result = pjp.proceed(); long end = System.currentTimeMillis(); log.info("请求耗时:{}ms", end - begin); log.info("请求返回:{}", JSON.toJSONString(result)); log.info("=============请求结束==========="); return result; } }

这边先不看代码的具体内容,先简单介绍一下用到AOP中常用的注解

@Aspect : 指定切面类;

@Pointcut:公共切入点表达式

通知方法

前置通知(@Before) 目标方法执行之前,执行注解的内容

后置通知(@After)目标方法执行之后,执行注解的内容

返回通知 (@AfterReturning)目标方法返回后,执行注解的内容

异常通知 (@AfterThrowing)目标方法抛出异常后,执行注解的内容

环绕通知 (@Around)目标方法执行前后,分别执行一些代码

注意 定义好切片类后要将其加入Spring容器内才能使用哦 (可以使用@Component注解)

3. 具体实现(一个例子) 1.首先定义一个注解,代码如下 /** * @Author Song * @Date 2020/5/26 9:44 * @Version 1.0 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented public @interface EagleEye { /** * @Retention(RetentionPolicy.RUNTIME) * 定义了注解的生命周期为运行时 * <p> * @Target(ElementType.METHOD) * 定义了注解的作用域为方法 * <p> * Documented * 标识该注解可以被JavaDoc记录 * <p> * 定义注解名称为EagleEye(鹰眼,哈哈~~) * <p> * 定义一个元素desc,用来描述被修饰的方法 * <p> * 接口描述 * * @return */ String desc() default ""; } 2.定义切片内并写好自己想要增强的方法

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wspzgd.html