java之注解
引言
- 什么是注解?有哪些必要知识?
- 内置注解?
- 元注解?
- 注解的使用场景
- 注意事项
java.lang.annotation.Annotation
中有说明:这是所有注解类型必须继承的公共接口。
以java中提供的@Override
注解为例,一个由Override
标识的方法声明意为着它将重写父类中中的方法声明。
1 |
|
等价于
1 | public interface Override extends Annotation{} |
元注解
什么是元注解?『它是用于修饰注解的注解,通常用在注解的定义上。例如上面Override
注解上的@Target
和@Retention
。
java 5中定义了如下四种元注解:
@Target
: 定义了注解的作用目标@Retention
:定义注解的生命周期@Documented
: 注解是否应当被保留在JavaDoc中@Inherited
:是否允许子类继承该注解
@Target
@Target
用以标识该注解所能出现的位置,具体枚举值定义在java.lang.annotation.ElementType
中:
1 | public enum ElementType { |
@Retention
用以描述注解的生命周期,有如下三种取值:
RetentionPolicy.SOURCE
: 仅在编译器可见,不写入class源文件RetentionPolicy.CLASS
:编译器编译为class源文件时存在,在类加载阶段丢弃RetentionPolicy.RUNTIME
: 运行时仍存在
@Documented
注解是否应当被保留在JavaDoc中
@Inherited
@Inherited
注解,是指定某个自定义注解如果写在了父类的声明部分,那么子类的声明部分也能自动拥有该注解。@Inherited
注解只对那些@Target
被定义为 ElementType.TYPE
的自定义注解起作用。
如何自定义注解
自定义注解有两种实现:
- 基于拦截器
- 基于 aop
下文中,在介绍完如何定义注解后,将分别以拦截器模式和aop方式实现登录校验。
自定义注解
如下指定了一个自定义注解LoginRequired
,该注解作用于方法。被编译器保存在class文件中,而且在运行时会被JVM保留,可以通过反射读取;
1 |
|
实现自定义注解有两种方式:
- 基于AOP切面
- 基于拦截器
基于拦截器实现自定义注解
配置 aop 切面
@Aspect
:声明该类为一个注解类;@Pointcut
:定义一个切点,后面跟随一个表达式,表达式可以定义为切某个注解,也可以切某个package
下的方法;
在配置 aop切面前需要先描述相关术语:
Spring AOP 相关术语
- 切面
Aspect
:在Spring AOP
中,切面可以使用通用类或者在普通类中以@Aspect
注解(@AspectJ
风格)来实现 - 连接点
Joinpoint
:在Spring AOP中一个连接点代表一个方法的执行 - 通知
Advice
:在切面的某个特定的连接点Joinpoint
上执行的动作。通知有各种类型,其中包括around
、before
和after
等通知。许多AOP框架,包括Spring,都是以拦截器做通知模型, 并维护一个以连接点为中心的拦截器链 - 切入点
Pointcut
:定义出一个或一组方法,当执行这些方法时可产生通知,Spring
缺省使用AspectJ
切入点语法。
通知类型
- 前置通知
@Before
:在某连接点join point
之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常) - 返回后通知
@AfterReturning
:在某连接点join point
正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回 - 抛出异常后通知
@AfterThrowing
:方法抛出异常退出时执行的通知 - 后通知
@After
:当某连接点退出的时候执行的通知(不论是正常返回还是异常退出) - 环绕通知
@Around
:包围一个连接点join point
的通知,如方法调用。这是最强大的一种通知类型,环绕通知可以在方法调用前后完成自定义的行为,它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行
执行顺序如下:
Spring AOP 配置的两种风格
- XML风格 = 采用声明形式实现Spring AOP
- AspectJ风格 = 采用注解形式实现Spring AOP
配置aop
使用场景
自定义注解+拦截器 实现登录校验
自定义注解+AOP 实现日志打印
引用
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 mqray's blog!
评论