Java支持注解形式,合理使用注解,可以对我们的编程提供极大的便利。JAVA自身提供了三种注解,分别是:@Override,@Deprecated,@SuppreWarnings.大家平时应该看见这个这三个注解,除此之外,我们还可以自定义注解。对于自定义的注解,可以加上自己的处理逻辑,这样在某些场合,我们就可以用注解标示某些类或这个方法,这样即可做到不侵入类或者方法内部修改代码,就可以完成我们指定的功能,很是方便。

一、 JAVA自定义注解

@interface MyAnnotation{}

一个最基本的Java自定义注解形式如上所示,但是,有一些点需要注意下:

1、注解内方法不能抛出任何异常;

2、方法应该返回以下之一:基本数据类型, 字符串, 类, 枚举或这些类型的数组形式.

3、注解内方法不能有任何参数;

4、必须使用@interface来定义其为一个注解;

5、注解内方法方法可以设置一个默认值;

1.1、注解类型

主要有三种类型的注解:

java-annotation-types.jpg

1)Marker Annotation

注解没有任何方法,就称为Marker annotation,比如:

@interface MyAnnotation{}

比如java中的@Override 和@Deprecated 注解就是 marker annotation.

2) Single-Value Annotaion

只有一个方法的注解就称为Annotation,比如:

@interface MyAnnotation{

int value();

}

我们可以提供默认值,比如:

@interface MyAnnotation{

int value() default 0;

}

应用这个注解示例如下:

@MyAnnotation(value=10)

其中value可以设置为任何int数值。

3)Multi-Value Annotation

如果一个注解有超过一个方法,那么就称为Multi-Value annotation。比如:

@interface MyAnnotation{

int value1();

String value2();

String value3();

}

我们可以为注解的方法提供默认值,比如:

@interface MyAnnotation{

int value1() default 1;

String value2() default "";

String value3() default "xyz";

}

应用这个注解示例如下:

@MyAnnotation(value1=10,value2="Arun Kumar",value3="Ghaziabad")

1.2、Java元注解

Java有四种元注解,元注解专职负责注解其他的注解:

@Target

@Target表示该注解可以用于什么地方,它的ElementType参数包括

Element

应用对象

TYPE

class, interface or enumeration

FIELD

fields

METHOD

methods

CONSTRUCTOR

constructors

LOCAL_VARIABLE

local variables

ANNOTATION_TYPE

annotation type

PARAMETER

parameter

例如我们的注解可以应用在类上,那么定义如下:

@Target(ElementType.TYPE)

@interface MyAnnotation{

int value1();

String value2();

}

@Retention

@Retention表示需要在什么级别保存该注解信息。可选的RententionPolicy参数

RetentionPolicy

Availability

RetentionPolicy.SOURCE

refers to the source code, discarded during compilation. It will not be available in the compiled class.

RetentionPolicy.CLASS

refers to the .class file, available to java compiler but not to JVM . It is included in the class file.

RetentionPolicy.RUNTIME

refers to the runtime, available to java compiler and JVM .

举个RetentionPolicy.RUNTIME的注解例子:

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

@interface MyAnnotation{

int value1();

String value2();

}

@Inherited

默认情况下, 注解是不能被自类继承的,加上@Inherited后,则允许子类继承父类中的注解。

@Inherited

@interface ForEveryone { }//Now it will be available to subclass also

@interface ForEveryone { }

class Superclass{}

class Subclass extends Superclass{}

@Documented

@Documented表示将此注解包含在javadoc中。

1.3、Demo示例

举个简单的从创建到应用的完整例子:

//Creating annotation

import java.lang.annotation.*;

import java.lang.reflect.*;

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

@interface MyAnnotation{

int value();

}

//Applying annotation

class Hello{

@MyAnnotation(value=10)

public void sayHello(){

System.out.println("hello annotation");

}

}

//Accessing annotation

class TestCustomAnnotation1{

public static void main(String args[])throws Exception{

Hello h=new Hello();

Method m=h.getClass().getMethod("sayHello");

MyAnnotation manno=m.getAnnotation(MyAnnotation.class);

System.out.println("value is: "+manno.value());

}

}

程序最重输出:value is: 10

二、注解应用(切片)

定义好注解后,重点是我们怎么灵活的应用注解。我先举个我自定义注解的应用场景,我的接口需要权限校验,具体流程为:方法传进去三个参数:资源,操作,资源ID,然后调用权限校验方法校验我的权限。

按照常规方法,那么在每个需要权限校验的接口处,就需要添加权限校验的代码,这样每次都要侵入方法内部添加代码,很是不方便,这时,我们就可以自定义一个注解了!

2.1 自定义注解切片应用

2.1.1、我的自定义注解:

我的注解定义如下:

/**

* Permission annotation, check if user has target permission, the permission is composed of "resource:operate:idKey".

*

*

* The target permission tuple is "resource:operate:idKey". For

* convenience, the 'idkey' params can be id or the key of id,if the 'idkey' params value can parse into Integer type, it is id,

* otherwise,it is the key of id, we should retrieve id by the key.

*

*

*

* "P:CREATE:1", it is a permission tuple,and the param of 'idKey' is id.

* "P:CREATE:ProductId", it is a permission tuple, and the param of 'idKey' is the key of id ,so we should retrieve id by the key .

*

*

* @author pioneeryi

* @since 2019-07-30 19:20

**/

@Target({ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Mapping

@Documented

public @interface HasPermission {

String resource();

String operate();

String idKey();

}

2.1.2、我的切片逻辑

为了应用这个注解,我需要对每个加了注解的方法进行切片:

@Aspect

public class AuthorizeAspect {

private Logger logger = LoggerFactory.getLogger(AuthzProcessor.class);

AuthzProcessor authzProcess = new AuthzProcessor();

@Pointcut("execution(* *(..))&&@annotation(com.tencent.dcf.authz.annotation.HasPermission)")

public void authorizePointCut() {

}

@Around("authorizePointCut()")

public Object permissionCheck(ProceedingJoinPoint joinPoint) throws Throwable {

if (!authzProcess.before(joinPoint)) {

return authzProcess.aheadReturn(joinPoint);

}

Object result = joinPoint.proceed();

return result;

}

}

通过如上切片,即可对每个加了@HasPermission的方法进行切片,切片后,处理逻辑如下:

public class AuthzProcessor implements AopProcessor {

private Logger logger = LoggerFactory.getLogger(AuthzProcessor.class);

private ShiroAuthorize authorize = new ShiroAuthorize();

//default set auth enable

private boolean authEnable = true;

@Override

public void enable(boolean enable) {

this.authEnable = enable;

}

@Override

public boolean before(ProceedingJoinPoint joinPoint) {

if (!authEnable) {

return true;

}

Permission permission = getHasPermission(joinPoint);

try {

return authorize.hasPermission(permission.getResource(), permission.getOperate(), permission.getResourceId());

} catch (Exception exception) {

logger.warn("user authorize occurs exception {}", exception.getMessage());

}

return false;

}

@Override

public Object aheadReturn(ProceedingJoinPoint joinPoint) {

throw new DcfAuthorizationException("Authorize failed");

}

@Override

public void after(ProceedingJoinPoint joinPoint, Object result, long startTime) {

}

private Permission getHasPermission(ProceedingJoinPoint joinPoint) {

MethodSignature signature = (MethodSignature) joinPoint.getSignature();

Method method = signature.getMethod();

HasPermission hasPermission = method.getAnnotation(HasPermission.class);

if (hasPermission == null) {

throw new RuntimeException("Horizon annotation is null");

}

String resource = hasPermission.resource();

String operate = hasPermission.operate();

String resourceId = getResourceId(hasPermission, joinPoint);

Permission permission = new Permission(resource, operate, resourceId);

return permission;

}

}

其中,我们在getHasPermission中获取注解的所有值,然后进行权限校验。

2.1.3、自定义注解使用

举一个我的自定义注解应用例子:

@CommandHandler

@HasPermission(resouce="P",operate="create",idKey="productId")

public void handle(CreateProductCommand command) throws ModifyRequirementException, AuthorizationException {

...

}

其中@CommandHandler是AXON框架的注解,因为我们项目均采用领域驱动模式,对领域驱动有兴趣,可以看我的另一篇关于领域驱动的文章。此时,我们只需要一个注解即可搞定权限校验。

切片生效的方法

切片如何生效,遇到一些坑,这里记录下,如何让切片生效的方法。

方法一:在maven中加入如下plugin(注意版本)

org.codehaus.mojo

aspectj-maven-plugin

1.9

1.8

1.8

true

1.8

true

compile

test-compile

方法二:Spring项目中,注入外部定义好的切片Bean.

@Configuration

@EnableAspectJAutoProxy

public class AspectConfig {

@Bean

public AuthorizeAspect authorizeAspect() {

return new AuthorizeAspect();

}

}

方法三:Spring项目中,定义切片时加上@Component

@Aspect

@Component

public class AuthorizeAspect {

}

三、总结

本文主要是总结了一下如何自定义注解,以及如何切片注解。并举了我自己的完整例子完整阐述从定义注解,到切片,以及应用主机的整个过程。

祝工作顺利, 天天开心!

java 切片_JAVA自定义注解并切片应用相关推荐

  1. Java通过自定义注解执行方法_Java自定义注解(使用篇)

    TL;DR Java 注解广泛运用在开发之中,用于增强变量/方法/类等. 尝试说明 Java 自定义注解的使用,以及通过开源项目中的使用进行说明. 本文主要记录个人的理解,全文基于Java SE8. ...

  2. java 自定义注解 解析_java自定义注解

    1.Annotation的工作原理: JDK5.0中提供了注解的功能,允许开发者定义和使用自己的注解类型.该功能由一个定义注解类型的语法和描述一个注解声明的语法,读取注解的API,一个使用注解修饰的c ...

  3. java自定义注解为空值_java自定义注解

    1. Java注解(Annotation) Java注解是附加在代码中的一些元信息,用于一些工具在编译. 运行时进行解析和使用,起到说明.配置的功能. 注解相关类都包含在java.lang.annot ...

  4. java 自定义注解获取_Java自定义注解

    Java在1.5开始引入了注解,目前流行的框架都在用注解,可想而知注解的强大之处. 以下通过自定义注解来深入了解java注解. 一.创建自定义注解 package com.sam.annotation ...

  5. java运行时读取注解_Java自定义注解和运行时靠反射获取注解

    转:1.Annotation的工作原理: JDK5.0中提供了注解的功能,允许开发者定义和使用自己的注解类型.该功能由一个定义注解类型的语法和描述一个注解声明的语法,读取注解的API,一个使用注解修饰 ...

  6. java 获取类的注解_Java 自定义注解通过反射获取类、方法、属性上的注解

    反射 JAVA中的反射是运行中的程序检查自己和软件运行环境的能力,它可以根据它发现的进行改变.通俗的讲就是反射可以在运行时根据指定的类名获得类的信息. 注解的定义 注解通过 @interface 关键 ...

  7. java注解获取参数_JAVA 自定义注解及参数获取 | 学步园

    package com.java.annotation; import java.lang.annotation.*; /** * Created by lw on 14-5-30. * 自定义注解 ...

  8. java注解约束参数为固定值_java自定义注解的实现及属性设置

    java自定义注解,元注解的使用 ,元注解中值详解 元注解:用于注解注解的注解... 元注解共有4个: ①.@Target:用于明确注解用于目标类的哪个位置 ElementType枚举类的值: Typ ...

  9. java自定义字段_Java自定义注解实战

    注解简介 注解的本质是一个接口,该接口默认继承Annotation接口,使用@interface进行定义.注解主要有三类:元注解.自定义注解以及框架定义的注解. 接口里面的成员方法称为注解的属性 定义 ...

最新文章

  1. IIS异常:CS0016: 未能写入输出文件“c:\WINDOWS\Microsoft.NET\Framework\.。。”--“拒绝访问...
  2. JS基础-Array对象手册
  3. 奇瑞汽车鸿蒙系统,华为鸿蒙OS系统汽车来了!国产汽车巨头奇瑞全球首发:开启崛起之路...
  4. applicationContext.xml中设置读取jdbc.properties文件
  5. jsoup HTML parser hello world examples--转
  6. lua excel to mysql_在Lua程序中使用MySQL的教程
  7. 用户故事(一):什么是用户故事?
  8. matlab可以做什么,matlab仿真用来干什么
  9. 计算机的桌面图标不见,桌面图标不见了怎么办,小编教你电脑桌面图标不见了怎么办...
  10. 计算前复权和后复权价格?A股复权因子的使用
  11. 1135: [POI2009]Lyz
  12. android-smart-image-view图片加载简单使用
  13. 【智能无线小车系列四】树莓派操作系统安装
  14. python英语查询词典-随堂作业
  15. 当当网电子书能打印吗_一行代码就能写一个日志打印组件,你信吗?为你揭晓RTOS中日志打印组件的核心
  16. ubuntu安装有道
  17. ios 查看app 包名 id
  18. 无效的m3u8怎么办_求教: 用 ckplayer 网页播放 m3u8 的直播无法播放,是什么问题?...
  19. C#和vb.net代码相互转换,翻译
  20. 谷歌宣布退出中国内地 网民何去何从?

热门文章

  1. 计算机中office是应用软件吗,如何从Win10计算机中卸载单个Office 365应用程序
  2. Python 虚拟环境管理工具(详细)
  3. 计算机软考中级排名,计算机软考中级哪个最容易过
  4. wps如何调整字符宽度_WPS文字中当字体字号放大到100时字距变宽如何适当调整字距...
  5. adobe premiere做平衡分屏、不等距分屏、多角度效果
  6. 预测泰坦尼克号生存问题
  7. 技术分享 | MySQL中MGR中SECONDARY节点磁盘满,导致mysqld进程被OOM Killed
  8. Java网络编程(6)NIO - Channel详解
  9. 不断进场的各大巨头,不断发布的云游戏产品(10.28记录)
  10. Vue 子组件v-shou无法在父组件中更新状态