2626 * [ Java技术江湖] ( #java技术江湖 )
2727 * [ 个人公众号:黄小斜] ( #个人公众号:黄小斜 )
2828
29-
30- ---
31- title: 夯实Java基础系列15:Java注解简介和最佳实践
32- date: 2019-9-15 15:56:26 # 文章生成时间,一般不改
33- categories:
34- - Java技术江湖
35- - Java基础
36- tags:
37- - annotation
38- - Java注解
39- ---
40-
4129本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看
4230> https://github.com/h2pl/Java-Tutorial
4331
@@ -73,9 +61,7 @@ Annotation 中文译过来就是注解、标释的意思,在 Java 中注解是
7361
7462并且,往抽象地说,标签并不一定是一张纸,它可以是对人和事物的属性评价。也就是说,标签具备对于抽象事物的解释。
7563
76- ![ ] ( https://img-blog.csdn.net/20170627213419176?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYnJpYmx1ZQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast )
77-
78-
64+ ![ ] ( https://java-tutorial.oss-cn-shanghai.aliyuncs.com/20230403213103.png )
7965
8066所以,基于如此,我完成了自我的知识认知升级,我决定用标签来解释注解。
8167
@@ -166,8 +152,8 @@ java.lang.annotation提供了四种元注解,专门注解其他的注解(在
166152JDK 内置注解
167153先来看几个 Java 内置的注解,让大家热热身。
168154
169- @Override 演示
170-
155+ @Override 演示
156+ ````
171157 class Parent {
172158 public void run() {
173159 }
@@ -182,7 +168,9 @@ JDK 内置注解
182168 public void run() {
183169 }
184170 }
171+ ````
185172@Deprecated 演示
173+ ````
186174class Parent {
187175
188176 /**
@@ -201,16 +189,20 @@ class Parent {
201189 parent.run(); // 在编译器中此方法会显示过时标志
202190 }
203191 }
192+ ````
204193@SuppressWarnings 演示
194+ ````
205195class Parent {
206196
207197 // 因为定义的 name 没有使用,那么编译器就会有警告,这时候使用此注解可以屏蔽掉警告
208198 // 即任意不想看到的编译时期的警告都可以用此注解屏蔽掉,但是不推荐,有警告的代码最好还是处理一下
209199 @SuppressWarnings("all")
210200 private String name;
211201 }
212-
202+ ````
213203@FunctionalInterface 演示
204+
205+ ````
214206/**
215207 * 此注解是 Java8 提出的函数式接口,接口中只允许有一个抽象方法
216208 * 加上这个注解之后,类中多一个抽象方法或者少一个抽象方法都会报错
@@ -219,7 +211,7 @@ class Parent {
219211interface Func {
220212 void run();
221213}
222-
214+ ````
223215
224216## 注解处理器实战
225217
@@ -230,27 +222,30 @@ interface Func {
230222我们先来了解下如何通过在运行时使用反射获取在程序中的使用的注解信息。如下类注解和方法注解。
231223
232224类注解
233- Class aClass = ApiController.class;
234- Annotation[ ] annotations = aClass.getAnnotations();
235-
236- for(Annotation annotation : annotations) {
237- if(annotation instanceof ApiAuthAnnotation) {
238- ApiAuthAnnotation apiAuthAnnotation = (ApiAuthAnnotation) annotation;
239- System.out.println("name: " + apiAuthAnnotation.name());
240- System.out.println("age: " + apiAuthAnnotation.age());
241- }
225+
226+ ````
227+ Class aClass = ApiController.class;
228+ Annotation[] annotations = aClass.getAnnotations();
229+
230+ for(Annotation annotation : annotations) {
231+ if(annotation instanceof ApiAuthAnnotation) {
232+ ApiAuthAnnotation apiAuthAnnotation = (ApiAuthAnnotation) annotation;
233+ System.out.println("name: " + apiAuthAnnotation.name());
234+ System.out.println("age: " + apiAuthAnnotation.age());
242235 }
243- 方法注解
244- Method method = ... //通过反射获取方法对象
245- Annotation[ ] annotations = method.getDeclaredAnnotations();
246-
247- for(Annotation annotation : annotations) {
248- if(annotation instanceof ApiAuthAnnotation) {
249- ApiAuthAnnotation apiAuthAnnotation = (ApiAuthAnnotation) annotation;
250- System.out.println("name: " + apiAuthAnnotation.name());
251- System.out.println("age: " + apiAuthAnnotation.age());
252- }
253- }
236+ }
237+ 方法注解
238+ Method method = ... //通过反射获取方法对象
239+ Annotation[] annotations = method.getDeclaredAnnotations();
240+
241+ for(Annotation annotation : annotations) {
242+ if(annotation instanceof ApiAuthAnnotation) {
243+ ApiAuthAnnotation apiAuthAnnotation = (ApiAuthAnnotation) annotation;
244+ System.out.println("name: " + apiAuthAnnotation.name());
245+ System.out.println("age: " + apiAuthAnnotation.age());
246+ }
247+ }
248+ ````
254249此部分内容可参考: 通过反射获取注解信息
255250
256251注解处理器实战
@@ -260,33 +255,33 @@ interface Func {
260255接下来要做的事情: 写一个切面,拦截浏览器访问带注解的接口,取出注解信息,判断年龄来确定是否可以继续访问。
261256
262257在 dispatcher-servlet.xml 文件中定义 aop 切面
263-
264- <aop:config>
265- <!--定义切点,切的是我们自定义的注解-->
266- <aop:pointcut id="apiAuthAnnotation" expression="@annotation(cn.caijiajia.devops.aspect.ApiAuthAnnotation)"/>
267- <!--定义切面,切点是 apiAuthAnnotation,切面类即注解处理器是 apiAuthAspect,主处理逻辑在方法名为 auth 的方法中-->
268- <aop:aspect ref="apiAuthAspect">
269- <aop:around method="auth" pointcut-ref="apiAuthAnnotation"/>
270- </aop:aspect>
271- </aop:config>
258+ ````
259+ <aop:config>
260+ <!--定义切点,切的是我们自定义的注解-->
261+ <aop:pointcut id="apiAuthAnnotation" expression="@annotation(cn.caijiajia.devops.aspect.ApiAuthAnnotation)"/>
262+ <!--定义切面,切点是 apiAuthAnnotation,切面类即注解处理器是 apiAuthAspect,主处理逻辑在方法名为 auth 的方法中-->
263+ <aop:aspect ref="apiAuthAspect">
264+ <aop:around method="auth" pointcut-ref="apiAuthAnnotation"/>
265+ </aop:aspect>
266+ </aop:config>
267+ ````
272268切面类处理逻辑即注解处理器代码如
273-
274- @Component("apiAuthAspect")
275- public class ApiAuthAspect {
276-
277- public Object auth(ProceedingJoinPoint pjp) throws Throwable {
278- Method method = ((MethodSignature) pjp.getSignature()).getMethod();
279- ApiAuthAnnotation apiAuthAnnotation = method.getAnnotation(ApiAuthAnnotation.class);
280- Integer age = apiAuthAnnotation.age();
281- if (age > 18) {
282- return pjp.proceed();
283- } else {
284- throw new RuntimeException("你未满18岁,禁止访问");
285- }
269+ ````
270+ @Component("apiAuthAspect")
271+ public class ApiAuthAspect {
272+
273+ public Object auth(ProceedingJoinPoint pjp) throws Throwable {
274+ Method method = ((MethodSignature) pjp.getSignature()).getMethod();
275+ ApiAuthAnnotation apiAuthAnnotation = method.getAnnotation(ApiAuthAnnotation.class);
276+ Integer age = apiAuthAnnotation.age();
277+ if (age > 18) {
278+ return pjp.proceed();
279+ } else {
280+ throw new RuntimeException("你未满18岁,禁止访问");
286281 }
287282 }
288-
289-
283+ }
284+ ````
290285
291286## 不同类型的注解
292287
@@ -295,7 +290,7 @@ interface Func {
295290你可以在运行期访问类,方法或者变量的注解信息,下是一个访问类注解的例子:
296291
297292```
298- Class aClass = TheClass.class;
293+ Class aClass = TheClass.class;
299294Annotation[] annotations = aClass.getAnnotations();
300295
301296for(Annotation annotation : annotations){
0 commit comments