小高教程网站源码分享,小高技术教程

各位老铁们好,相信很多人对小高教程网站源码分享都不是特别的了解,因此呢,今天就来为大家分享下关于小高教程网站源码分享以及小高技术教程的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧!

最近的文章系列相信大家也都发现了,都是一些比较基础的Java知识点。但是不知道在大家看了之后有没有觉得就是一些很基础的知识点,看样子挺简单的,其实还有挺多内容不会的。只有地基打牢了,开发才能跟更有效率,不要急于求成,不妨回头务实一番,别有收获。所以这期还是老样子,小编和伙伴们一起来学习注解的使用。

初识

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

注解是在Java1.5之后引入的,它可以提供用来完整地描述程序中所需的信息,可以由编译器来测试和验证的格式,存储有关程序的额外信息。

注解的使用很简单,只需要和@符号搭配。有些Java初学者常常会把注解注释混淆,但是两者的作用却大同小异,都是用来描述信息,不同的是注解描述的信息是给应用程序看的,而注释描述的信息是给开发人员看的。

初学者对注解的印象可能不深,注解也许不起眼但是处处可见。

最常见到的便是@Override,表示当前的方法定义将覆盖父类的方法,如果拼写错误,或者方法签名对不上被覆盖的方法,编译器就会发出错误提示。

既然都说到@Override注解了,那仔细回忆下,脑子里估计就浮现出@SuppressWarnnings注解。还记得我最早见到这个注解的时候,还是Myeclipse提示我使用的,我也不管三七二十一,就给标注上了。后来才知道这个注解是用来关闭编译器对类、方法、成员变量、变量初始化的警告。

上面两个都说完了,那不妨再来一个,这个可能是最不常见的。那就是@Deprecated

不要因为这个类加了横线感到奇怪,那是因为@Deprecated的效果。它的具体功能就是用于标识方法或类,标识该类或方法已过时,建议不要使用。如果开发人员使用了注解为它的元素,那么编译器就会发出警告信息。

刚刚开局不久,我们就已经学到了三个注解的使用,虽然只是基本的,但接下来我们就通过这三个注解为导线通关打怪吧。

首关之程娲造注

注解一旦构造出来,就享有编译器的类型检查保护。让我们先看下一组代码热热身:

publicclassTestService{\n\n@MyAnnotation\npublicvoidrunTset(){\nSystem.out.println(&34;);\n}\n\n}\n复制代码

不要纳闷,Java中确实没有一个注解名为MyAnnotation,但这个怎么来的呢,就是我们自己造的。

那么关子卖完了,接下来就来揭秘注解的制造:

@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic@interfaceMyAnnotation{\n}\n复制代码

这样子,一个简单的注解就新鲜出炉了。需要注意的是这可不是一个接口,需要留言interface前面还有一个@,这个标识要是漏掉了,那可以天差地别。

细心的小伙伴可能注意到了,定义的注解头上怎么还有注解。

这就是接下来要讲到,敲黑板,注意看!

元注解来帮忙

在定义注解时,会需要一些元注解。上面出现了两个,分别是@Target和@Retention.

其中@Target用来定义你的注解将应用于什么地方(例如一个方法或一个域),@Retention用来定义该注解在哪一个级别可用,在源代码中(SOURCE),类文件中(CLASS)或者运行时(RUNTIME)。Java提供了四种元注解,如下:

名称

用处

@Target

标识该注解可以用于什么地方。其中ElementType参数包括:1.CONSTARUCTOR:构造器的声明2.FIELD:域声明(包括enum实例)3.LOCAL_VARIABLE:局部变量声明4.METHOD:方法声明5.PACKAGE:包声明6.TYPE:类、接口(包括注解类型)或enum声明

@Retention

表示需要在什么级别保存该注解信息,其中RetentionPolicy参数包括:1.SOURCE:注解将被编译器丢弃2.CLASS:注解在class文件中可用,但会被VM丢弃3.RUNTIME:VM将在运行期也保留注解,因此可以通过反射机制读取注解的信息

@Documented

将此注解包含在JavaDoc中

@Inherited

允许子类继承父类的注解

注解也分类

我们在上面示例中创建了一个@MyAnnotation注解。看起来很简单,没什么内容,因此这种注解我们也称为标记注解,注解也分几类:

标记注解:注解内部没有属性。使用方式:@注解名

//定义\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic@interfaceMyAnnotation{\n}\n复制代码

单值注解:注解内部只有一个属性。使用方式:@注解名(key=value)

//定义\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic@interfaceSingleValueAnnotation{\nStringname();\n}\n//使用\n@SingleValueAnnotation(name=&34;)\npublicvoidsingleTest(){}\n复制代码

多值注解:注解内部有过个属性。使用方式:@注解名(key=value,key=value,…)

//定义\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic@interfaceMultiValueAnnotation{\nStringname();\nintnum();\n}\n//使用\n@MultiValueAnnotation(name=&34;,num=1)\npublicvoidmultiTest(){}\n复制代码

值也有默认

当我们使用的不是标记注解时,如果在使用注解的时候不给注解中的属性赋上值,那么编译器就会报错,提示我们需要赋值。

这样子是很不方便,有时候我们并没有使用到或值是固定的不想重复写,那么这个时候就需要借助default关键字来帮忙我们解决这种问题。

@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic@interfaceMultiValueAnnotation{\n\nStringname();\n\nintnum()default0;\n}\n复制代码

我们在属性上使用了default关键字来声明num属性的默认值为0,这样子我们在使用上述那个注解的时候就可以不用手动给num赋值了。

次关之造器解注

注解具有让编译器进行编译检查的作用,但是如果没有用来读取注解的工具,那注解也不会比注释更有用,起码注释可以让开发人员更直观的看到此段代码的用处。

重回反射

想要创建与使用注解处理器,我们还需要借助反射机制来构造这类工具。以下是简单的例子:

publicclassAnnotationHandle{\n\npublicstaticvoidtrack(Class<?>c){\nfor(Methodm:c.getDeclaredMethods()){\nMultiValueAnnotationannotation=m.getAnnotation(MultiValueAnnotation.class);\nif(annotation!=null){\nSystem.out.println(&34;+annotation.name()+\n&34;+annotation.num());\n}\n}\n}\n\npublicstaticvoidmain(String[]args){\ntrack(TestService.class);\n}\n}\n\n/*OUTPUT:\nname:test\nnum:0\n*/\n复制代码

在上述例子中我们用到了两个反射的方法:getDeclaredMethods()和getAnnotation()。

其中getDeclaredMethods()用来返回该类的所有方法,getAnnotation()用来获取指定类型的注解对象。如果方法上没有该注解则会返回null值。

注解元素可用类型

上述@MultiValueAnnotation注解中我们定义了String类型的name和int类型的num,除此之外我们还可以使用其他类型如下:

基本类型int、float、boolean等StringClassenumAnnotation以上类型的数组

如果使用了上面以外的其他类型,那么编译器就会报错。而且要注意的是,也不能使用基本类型的包装类型

默认值的限制

上述例子中我们也看到了,我们可以在使用注解的时候给注解属性赋值,也可以在定义注解的时候给注解一个默认值,但是这两者都说明了一件事:那就是,注解元素不能有不确定的值,要么具有默认值,要么在使用注解时提供元素的值

基本元素不存在null值,因此对于非基本类型的元素,无论是在使用中声明,还是在定义时声明,都不能将null值作为其值。因此在实际开发中,我们往往会定义一些特殊值作为不存在的标识,例如负数空字符串

三关之运注帷幄

在前面两关中,我们学会了定义注解和创建注解处理器。接下来我们就要来更加深入掌握注解!

注解也能嵌套

在修饰注解元素的时候我们看到可以使用Annotation来修饰,估计看到那的时候会觉得有点奇怪。在这里就来为你来揭秘。

先来看一组注解:

@Constraints

@Target(ElementType.FIELD)\n@Retention(RetentionPolicy.RUNTIME)\npublic@interfaceConstraints{\nbooleanprimaryKey()defaultfalse;\nbooleanunique()defaultfalse;\n}\n复制代码

@SQLString

@Target(ElementType.FIELD)\n@Retention(RetentionPolicy.RUNTIME)\npublic@interfaceSQLString{\nStringname()default&34;;\nConstraintsconstraints()default@Constraints;\n}\n复制代码

我们在@SQLString注解中使用Constraints注解元素,并将默认值设为@Constraints。这个时候Constraints中的值都是@Constraints注解中定义的默认值,如果我们要使用自定义的话,做法如下:

@Target(ElementType.FIELD)\n@Retention(RetentionPolicy.RUNTIME)\npublic@interfaceSQLString{\nStringname()default&34;;\nConstraintsconstraints()default@Constraints(primaryKey=true);\n}\n复制代码

这样子我们就可以使用自己定义的value

注解不支持继承

我们不能使用extends来继承某个@interface,但是可以通过嵌套的方式来解决这一烦恼。

AOP与注解的搭配

AOP在当今开发中我们并不陌生,那么AOP注解能产生什么化学反应呢,请看以下代码:

@ApiLog:

@Retention(RetentionPolicy.RUNTIME)\n@Target({ElementType.METHOD,ElementType.TYPE})\npublic@interfaceApiLog{\n/**\n*接口名称\n*/\nStringname();\n}\n复制代码

使用:

@GetMapping(value=&34;)\n@ApiLog(name=&34;)\npublicResultgetConfig()throwsException{\nreturnsendOK(SystemService.getConfig(type));\n}\n复制代码

Aop使用:

@Aspect\n@Component\npublicclassSysLogAspect{\n@Autowired\nprivateLogServicelogService;\n\n@Pointcut(&34;)\npublicvoidlogPointCut(){\n}\n\n@Around(&34;)\npublicObjectaround(ProceedingJoinPointpoint)throwsThrowable{\nlongbeginTime=System.currentTimeMillis();\n//执行方法\nObjectresult=point.proceed();\n//执行时长(毫秒)\nlongtime=System.currentTimeMillis()-beginTime;\n//保存日志\nsaveSysLog(point,time);\nreturnresult;\n}\n\nprivatevoidsaveSysLog(ProceedingJoinPointjoinPoint,longtime){\nMethodSignaturesignature=(MethodSignature)joinPoint.getSignature();\nMethodmethod=signature.getMethod();\n\nLogEntitylog=newLogEntity();\nApiLogapiLog=method.getAnnotation(ApiLog.class);\nif(apiLog!=null){\n//注解上的描述\nlog.setMethodDescribe(syslog.value());\n}\n\n//请求的方法名\nStringclassName=joinPoint.getTarget().getClass().getName();\nStringmethodName=signature.getName();\nlog.setMethod(className+&34;+methodName+&34;);\n\n//请求的参数\nObject[]args=joinPoint.getArgs();\nStringparams=JSON.toJSONString(args[0]);\nlog.setParams(params);\n\n//获取request\nHttpServletRequestrequest=((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();\n\n//设置IP地址\nlog.setIp(ServletUtil.getIpAddress(request));\n\n//用户名\nStringusername=LoginInfo.getUsername();\nlog.setUsername(username);\n\n//保存系统日志\nlogService.save(log);\n}\n}\n复制代码

通过以上代码,我们可以在期望记录日志的方法上增加@ApiLog注解,该方法的动作就会被记录进日志表,不管方法叫什么名字,类在什么位置,都可以轻松的解决,而且没有代码入侵!

到这里,我们已经成功地通过了三个关卡,相信你也充分掌握了注解的使用,这期注解咱们到此完结啦,切记:不可因小而不学,不可因大而弃之。

今天的你多努力一点,明天的你就能少说一句求人的话!原文链接:https://juejin.cn/post/6876773156560994311

OK,本文到此结束,希望对大家有所帮助。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平