浅论java中的注解

时间记录2019-4-1

学习注解 Annotation
首先注解是什么呢,注解有什么用呢,为什么需要注解,如何去使用注解呢,注解是怎么运行的呢?我们围绕这个问题开展学习。一提到注解详细很多人都会提到spring等框架中常用的,在这里我不讨论这些,搞懂了什么是注解再去学习相关的框架才是根本,不要一知半解。
一:注解的概念
说道注解很多人会想到一开始学习编程java编程时看到的最多的事注释,那么和注释有没有什么相似之处呢?注释是写给阅读代码的人看的,那么注解是写给谁看的呢?注解是写给代码和编译器看的。注释标记的事这块的代码是什么含义,那么注解也是表示了这块的代码是需要特殊干什么。像 @Override@Deprecated@Suppvisewarnings这些常见的。当然了注解只是标记下而已,有没有不影响正常的运行,但是对应的功能可能就没有了。
二:注解作用
注解的概念中介绍了注解的简单作用,在于标记,标记数据,标记方法,类等等自己需要的东西,描述某些特定的信息,个人觉得没有必要纠结于什么样子的数据,只要自己能用都行。当然是在考虑性能和可读性,可维护性的基础上了。
三:使用注解
使用注解当然得提到 @infterface ,和class一样作为一种关键字,实际上在对编译器来说一样,只是标记不同的内容而已,个人是这样认为的。
1:定义一个自己的注解
例如:

public @interface Face
{
}

2:注解的修饰注解(元注解)

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)

@Target
指示批注类型适用的上下文。这个注释类型可以是的声明上下文和类型上下文适用性在JLS 9.6.4.1中有规定,并在源代码中用枚举表示。
Indicates the contexts in which an annotation type is applicable. The declaration contexts and type contexts in which an annotation type may be applicable are specified in JLS 9.6.4.1, and denoted in source code by enum constants of
ElementType java.lang.annotation.ElementType
@Retention
指示带批注类型的批注的长度保留。如果上没有保留注释注释类型声明,保留策略默认为@code retentionpolicy.class。保留元批注只有在元注释类型直接用于注释。它没有如果将元注释类型用作中的成员类型,则产生效果另一个批注类型。
Indicates how long annotations with the annotated type are to
be retained. If no Retention annotation is present on an annotation type declaration, the retention policy defaults to {@code RetentionPolicy.CLASS}.

A Retention meta-annotation has effect only if the meta-annotated type is used directly for annotation. It has no effect if the meta-annotated type is used as a member type in another annotation type.
3:注解类的属性成员
注解的属性也叫做成员变量。注解只有成员变量,没有方法。注解的成员变量在注解的定义中以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。(我们和接口的定义对比下
采用default来赋值,或者在注解使用的时候赋值(当然了编译器会报错的,如果没有赋值)
例如:

package com.vking.engine.angelscript;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Face
{
	public int time() default 1;
}
package com.vking.engine.angelscript;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Face
{
	public int time();
}

package com.vking.engine.angelscript;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * test annotaion get
 * @author huoruilin
 */

public class TestAnnotation
{
	@Face(time = 0)
	public void face()
	{
        System.out.println("face");
	}

	public static void main(String[] args)
	{
		TestAnnotation app = new TestAnnotation();
		try
		{
			Method method = app.getClass().getMethod("face", null);
			Annotation[] annotations = method.getAnnotations();
		   	for(Annotation annostation : annotations)
		   	{
		   		System.out.println(annostation.annotationType().getSimpleName());
		   	}
		} catch (NoSuchMethodException | SecurityException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

4:如何获取到自己的注解
java中的Method、Class

java.lang.reflect.Method:
 byte[] getAnnotationBytes()
 public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
 public AnnotatedType getAnnotatedReturnType()
java.lang.Class:
 public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
 public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) 
 public Annotation[] getAnnotations() 
 AnnotationType getAnnotationType() 
 AnnotatedType getAnnotatedSuperclass()
 public AnnotatedType[] getAnnotatedInterfaces() 

简单测试使用

package com.vking.engine.angelscript;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Face
{
    
}
package com.vking.engine.angelscript;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * test annotaion get
 * @author huoruilin
 */
@Face
public class TestAnnotation
{
	public void face()
	{
        System.out.println("face");
	}

	public static void main(String[] args)
	{
		TestAnnotation app = new TestAnnotation();
		Annotation[] annotations = app.getClass().getAnnotations();
		for(Annotation annostation : annotations)
		{
			System.out.println(annostation.annotationType().getSimpleName());
		}
	}
}

输出结果为

 Face

即为我们在类上面添加的那个注解标记。
思考:我们获取到一个类上面的注解后是不是标记了这个类具有某种特殊的意义,是不是需要进行什么特殊的操作,故我们可以自行使用ClassLoader来实例化一个什么东西 然后这个东西带有特殊的注解我们就需要进行某种操作(可以自行尝试)

调整注解类型继续做下一步测试

package com.vking.engine.angelscript;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Face
{
    
}
package com.vking.engine.angelscript;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * test annotaion get
 * @author huoruilin
 */
public class TestAnnotation
{
	@Face
	public void face()
	{
        System.out.println("face");
	}

	public static void main(String[] args)
	{
		TestAnnotation app = new TestAnnotation();
		try
		{
			Method method = app.getClass().getMethod("face", null);
			Annotation[] annotations = method.getAnnotations();
		   	for(Annotation annostation : annotations)
		   	{
		   		System.out.println(annostation.annotationType().getSimpleName());
		   	}
		} catch (NoSuchMethodException | SecurityException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

输出结果为

扫描二维码关注公众号,回复: 5874835 查看本文章
Face

思考:在方法前面添加了一段标记,标记这我们需要去干什么事情。我们怎么去截获这个注解锁标记的内容呢。(代理模式?)

5:注解中的内容获取

package com.vking.engine.angelscript;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * test annotaion get
 * @author huoruilin
 */
public class TestAnnotation
{
	@Face(time = 0)
	public void face()
	{
        System.out.println("face");
	}

	public static void main(String[] args)
	{
		TestAnnotation app = new TestAnnotation();
		try
		{
			Method method = app.getClass().getMethod("face", null);
			Annotation[] annotations = method.getAnnotations();
		   	for(Annotation annostation : annotations)
		   	{
		   		if("Face".equals(annostation.annotationType().getSimpleName()))
		   		{
		   			System.out.println(((Face)annostation).time());
		   		}
		   	}
		} catch (NoSuchMethodException | SecurityException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

输出结果为

0

思考:注解的属性中我们可以写上写什么呢?可以做些什么事呢?

总结:注解只是一种标记性的东西,通知到某一个东西,这个东西可能是你的编译器,可能是你的代码,那么我们如何去截获呢,那么需要提出来的就是代理
代理可以了解设计模式的代理模式思想(静态代理和动态代理),具体实现可以了解如下(目前我知道的)

jdk中的代理:
java.lang.reflect.Proxy
开源项目:
cglib
asm
cglib是在asm的基础上面封装的

时间记录2019-4-13

下一篇:代理结合注解一起描述

猜你喜欢

转载自blog.csdn.net/justinhuo/article/details/88960286