注解和aop的简记
创始人
2024-05-31 03:47:25
0

注解和aop的简记

一、注解

常见的注解有如下

标准注解:

  • @Override : 表示当前方法将覆盖超类的方法
  • @Deprecated : 标记过时,如果使用了该注解标记的方法,将会报警。
  • @SuppressWarnings : 关闭警告信息。

1. 注解的释义

注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方法,使得我们可以在稍后某个时候非常方便地使用这些数据。

引自 Think in java。

2. 注解的使用

想要定义一个注解,需要元注解的帮助。

元注解:

  • @Target : 表示注解可以用到什么地方
  • @Retention : 表示需要在什么级别保存注解信息
  • @Documented :将注解包含在Javadoc中
  • @Inherited : 允许子类继承父类的注解

简单样例:

/*** 添加这个注解,可以统计方法的运行时间,* 且携带开发者相关信息* @author cay* @since 2023/02/07*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RunningTime {/*** 添加开发负责人的信息,方便对应人员修复bug* @return 开发者相关信息*/String authorMsg();
}

@Target

从上面的简单案例中可以看到 需要填加内容 ElementType, ElementType的是一个枚举类型。

public enum ElementType {/** Class, interface (including annotation type), or enum declaration */TYPE,/** Field declaration (includes enum constants) */FIELD,/** Method declaration */METHOD,/** Formal parameter declaration */PARAMETER,/** Constructor declaration */CONSTRUCTOR,/** Local variable declaration */LOCAL_VARIABLE,/** Annotation type declaration */ANNOTATION_TYPE,/** Package declaration */PACKAGE,/*** Type parameter declaration** @since 1.8*/TYPE_PARAMETER,/*** Use of a type** @since 1.8*/TYPE_USE
}

@Retention

用来表示需要在什么级别保存注解的信息。需要填写枚举类型 RetentionPolicy。

public enum RetentionPolicy {/*** Annotations are to be discarded by the compiler.*/SOURCE,/*** Annotations are to be recorded in the class file by the compiler* but need not be retained by the VM at run time.  This is the default* behavior.*/CLASS,/*** Annotations are to be recorded in the class file by the compiler and* retained by the VM at run time, so they may be read reflectively.** @see java.lang.reflect.AnnotatedElement*/RUNTIME
}

SOURCE 级别则只会在源码阶段存在,编译后就不存在。CLASS 则编译后依然会存在,但是不会jvm中保留。RUNTIME 则会一直存在到代码运行的时候,所以可以通过反射获得

SOURCE 级别简单示例

在常用的lombok中的日志注解:@Slf4j,就是默认在SOURCE级别上,编译之后就会消失,但是会做一定的操作。

@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE})
public @interface Slf4j {String topic() default "";
}

代码使用@Slf4j:

@Slf4j
public class Recommendation {/*** 需要增强的方法*/public void recommend() {log.info("推荐动漫: 一人之下");}
}

字节码中会将注解变成一句代码

public class Recommendation {//注解生成的语句private static final Logger log = LoggerFactory.getLogger(Recommendation.class);/*** 需要增强的方法*/public void recommend() {log.info("推荐动漫: 小妖怪的夏天");}
}

3. 使用样例

注解定义:

/*** 添加这个注解,可以统计方法的运行时间,* 且携带开发者相关信息* @author cay*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RunningTime {/*** 添加开发负责人的信息,方便对应人员修复bug* @return 开发者相关信息*/String authorMsg();
}

添加注解的方法

/*** 注解使用的样例* @author cay* @since 2023/02/07*/
@Slf4j
public class AnnotationSample {/*** 使用注解的方法*/@RunningTime(authorMsg = "cay")public void recommend() {log.info("推荐电视剧:今日宜加油");}
}

测试单元通过反射获取注解中的信息

/*** 通过反射获取注解的信息*/
@Test
public void testReflect() throws ClassNotFoundException {Class clazz = Class.forName("com.example.demo.simple.AnnotationSample");// 获取该类的所有方法Method[] declaredMethods = clazz.getDeclaredMethods();for (Method declaredMethod : declaredMethods) {if (declaredMethod.isAnnotationPresent(RunningTime.class)) {RunningTime annotation = declaredMethod.getAnnotation(RunningTime.class);String info = annotation.authorMsg();log.info("注解中存储的信息:{}", info);}}
}

注意:

**想要通过反射获取注解,则需要设置为 @Retention(RetentionPolicy.RUNTIME)。那么如果想要处理 SOURCE级别,就可以使用注解处理器Processor **

二、注解和Aop的结合使用

毕竟现在都是使用springboot框架,所以spring也帮我们简化了注解的使用,当自己想要根据注解去做些额外的事情的时候,和aop结合使用会非常的方便。

简单的使用案例,之前写过,就不在赘述了,链接如下

https://blog.csdn.net/weixin_44457062/article/details/128915444

三、AOP

既然提到了Aop,就顺便记录一下Spring中Aop的相关信息。

AOP(Aspect Oriented Programming),即面向切面编程,可以方便的用来统一处理日志、管理事务等,与业务逻辑分离。

相关概念

官网地址:

https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop

英文概念:

  • Aspect: A modularization of a concern that cuts across multiple classes. Transaction management is a good example of a crosscutting concern in enterprise Java applications. In Spring AOP, aspects are implemented by using regular classes (the schema-based approach) or regular classes annotated with the @Aspect annotation (the @AspectJ style).
  • Join point: A point during the execution of a program, such as the execution of a method or the handling of an exception. In Spring AOP, a join point always represents a method execution.
  • Advice: Action taken by an aspect at a particular join point. Different types of advice include “around”, “before” and “after” advice. (Advice types are discussed later.) Many AOP frameworks, including Spring, model an advice as an interceptor and maintain a chain of interceptors around the join point.
  • Pointcut: A predicate that matches join points. Advice is associated with a pointcut expression and runs at any join point matched by the pointcut (for example, the execution of a method with a certain name). The concept of join points as matched by pointcut expressions is central to AOP, and Spring uses the AspectJ pointcut expression language by default.
  • Introduction: Declaring additional methods or fields on behalf of a type. Spring AOP lets you introduce new interfaces (and a corresponding implementation) to any advised object. For example, you could use an introduction to make a bean implement an IsModified interface, to simplify caching. (An introduction is known as an inter-type declaration in the AspectJ community.)
  • Target object: An object being advised by one or more aspects. Also referred to as the “advised object”. Since Spring AOP is implemented by using runtime proxies, this object is always a proxied object.
  • AOP proxy: An object created by the AOP framework in order to implement the aspect contracts (advise method executions and so on). In the Spring Framework, an AOP proxy is a JDK dynamic proxy or a CGLIB proxy.
  • Weaving: linking aspects with other application types or objects to create an advised object. This can be done at compile time (using the AspectJ compiler, for example), load time, or at runtime. Spring AOP, like other pure Java AOP frameworks, performs weaving at runtime.

英文的顺序有点乱,自己按照概念排了一下序,大致意思(自己的理解):

  • Join point(连接点): 能都被拦截到的点,在spring中只有方法。在AOP联盟定义的规范里还有可能是字段或构造器
  • Advice(增强或通知): 对 Pointcut 的增强,即我们需要增强的逻辑
  • Pointcut(切入点): 将 Advice 和 Join point 连接起来。
  • Aspect (切面):Advice 、 Pointcut和 Join point 结合
  • Introduction(引介):可以引入额外的方法和字段。
  • Target object :代理的目标对象
  • AOP proxy:动态代理,有 JDK 动态代理和 CGLIB 代理
  • 将切面与其他应用程序类型或对象链接以创建代理的对象。这可以在编译时(例如使用AspectJ编译器)、加载时或运行时完成。与其他纯JavaAOP框架一样,SpringAOP在运行时执行编织。

spring AOP的简单使用

spring已经帮我们封装好了五种 advise,我们可以很简单的实现aop,实现对需要增强方法的增强逻辑。之前对总结过,就不赘述了,之前文章链接:

https://blog.csdn.net/weixin_44457062/article/details/128710179

JDK动态代理

注意:

  • spring默认的是 JDK 动态代理
  • spring boot 2.x 之后,spring boot默认是CGLIB 代理

jdk动态代理是基于接口,生成实现类,复写被增强类里的方法,然后在添加增强方法。

简单使用

  1. 待增强的接口
/*** @author cay*/
public interface IMyAopProxyService {public void myAopProxy();
}
  1. 实现类
/*** @author cay*/
@Slf4j
public class MyAopProxyServiceImpl implements IMyAopProxyService {@Overridepublic void myAopProxy() {log.info("aop proxy......");}
}
  1. 增强类
/*** aop测试的增强类* @author cay*/
@Slf4j
public class MyAopProxyAdvice {/*** 前置增强*/public void beforeMethod() {log.info("before advice ......");}/*** 后置增强*/public void afterMethod() {log.info("after advice ......");}
}
  1. JDK动态代理的测试单元
/*** 测试JDK动态代理*/
@Test
public void testJdkAopProxy() {//需要被增强的类,使用接口接收IMyAopProxyService myAopProxyService = new MyAopProxyServiceImpl();//增强类MyAopProxyAdvice myAopProxyAdvice = new MyAopProxyAdvice();//调用JDK动态代理Object proxy = Proxy.newProxyInstance(myAopProxyService.getClass().getClassLoader(), myAopProxyService.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {myAopProxyAdvice.beforeMethod();Object invoke = method.invoke(myAopProxyService, args);myAopProxyAdvice.afterMethod();return invoke;}});IMyAopProxyService jdkProxy = (IMyAopProxyService) proxy;log.info("aopProxy: {}", proxy);jdkProxy.myAopProxy();
}

CGLIB代理

CGLIB代理基于类,生成子类,子类覆盖父类方法,并添加增强方法。

spring boot 2.x 之后,spring boot默认是CGLIB 代理,spring的默认代理是 JDK 动态代理。

使用上面JDK代理创建的类,测试单元:

/*** 测试CGLIB代理*/
@Test
public void testCglibAopProxy() {//被增强的类,使用本类接收MyAopProxyServiceImpl myAopProxyService = new MyAopProxyServiceImpl();MyAopProxyAdvice myAopProxyAdvice = new MyAopProxyAdvice();Enhancer enhancer = new Enhancer();enhancer.setSuperclass(myAopProxyService.getClass());enhancer.setCallback(new MethodInterceptor() {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {myAopProxyAdvice.beforeMethod();Object invoke = methodProxy.invokeSuper(o, objects);myAopProxyAdvice.afterMethod();return invoke;}});Object o = enhancer.create();MyAopProxyServiceImpl cglibProxy = (MyAopProxyServiceImpl) o;log.info("cglibProxy:{}", cglibProxy);cglibProxy.myAopProxy();
}

相关内容

热门资讯

安卓系统表情包下载地址,安卓系... 你是不是也和我一样,对安卓系统的表情包爱不释手?那些搞笑的、可爱的、甚至是有点小调皮的表情,总能让我...
原生安卓系统声音bug,揭秘那... 你有没有遇到过这种情况?手机里突然传来一阵奇怪的声音,让你瞬间从美梦中惊醒,或者正在专心工作时被打扰...
水果收银机安卓系统,便捷高效的... 你有没有想过,在繁忙的超市里,那些摆满新鲜水果的摊位,背后竟然隐藏着一个小小的科技秘密?没错,就是那...
安卓系统变苹果界面了吗,苹果界... 最近手机界可是炸开了锅,不少安卓用户都在议论纷纷:“安卓系统变苹果界面了吗?”这事儿可真不简单,得好...
miui操作系统与安卓系统吗,... 亲爱的读者,你是否曾在手机上看到过MIUI操作系统和安卓系统这两个名字,好奇它们之间有什么区别?今天...
安卓系统怎么卡道具界面,探究原... 手机用久了,是不是感觉安卓系统越来越卡?尤其是那个道具界面,点开就慢吞吞的,真是让人头疼。别急,今天...
安卓系统红包加速器,畅享无阻新... 你有没有发现,现在用手机抢红包简直是一场速度与激情的较量?别急,别急,让我来给你揭秘一款神器——安卓...
安卓经典版系统更新时间,从首次... 你有没有发现,最近你的安卓手机又悄悄地变了个样?没错,就是那个陪伴我们多年的经典版系统,它又来更新啦...
安卓系统开发要多久,约需1-2... 你有没有想过,自己动手开发一个安卓应用,究竟需要多长时间呢?这可是个让人好奇的问题,毕竟安卓系统开发...
原生安卓系统手机壁纸图片,探索... 亲爱的手机控们,你是否曾为寻找一款独特的壁纸而烦恼?今天,就让我带你走进原生安卓系统手机壁纸的奇幻世...
bmw安卓互联系统,智能驾驶新... 你有没有发现,现在开车已经不仅仅是驾驶那么简单了?一辆好车,还得有个好“大脑”,这样才能让你的驾驶体...
安卓手机升级系统卡吗,安卓手机... 你有没有遇到过这种情况:安卓手机升级系统后,突然感觉手机像蜗牛一样慢吞吞的,心里那个急啊!今天,就让...
无线麦克风安卓系统,轻松实现无... 你有没有想过,在一场热闹的K歌派对或者重要的演讲场合,无线麦克风简直就是救星啊!想象你手握麦克风,自...
怎么重新定制安卓系统,打造专属... 你有没有想过,你的安卓手机其实可以变得独一无二,就像是你自己的小宇宙一样?没错,就是重新定制安卓系统...
安卓系统卡西欧照片软件,安卓系... 你有没有发现,手机用久了,尤其是安卓系统,有时候就像老牛拉破车,慢吞吞的,让人抓狂?这不,最近我就遇...
安卓pc版系统怎么下载,安卓P... 你有没有想过,在电脑上也能畅玩安卓手机上的游戏和应用呢?没错,这就是安卓PC版系统的魅力所在!今天,...
安卓系统软件语言,安卓系统软件... 你知道吗?在手机的世界里,安卓系统就像是个万能的魔法师,它不仅能变出各种各样的应用,还能让手机的语言...
鸿蒙其实还是安卓系统,揭开其背... 你知道吗?最近在科技圈里,有一个话题可是引起了不小的波澜呢!那就是鸿蒙系统,是不是听起来很高级?但别...
安卓刷机原系统,原系统深度解析... 你有没有想过,你的安卓手机是不是已经有点儿“老态龙钟”了呢?别急,别急,今天就来给你揭秘一下安卓刷机...
安卓java实现运行linux... 你有没有想过,在你的安卓手机上运行一个完整的Linux系统?听起来是不是很酷?想象你可以在安卓设备上...