一、定義Java文件叫做Annotation,用@interface表示。
br/>Java文件叫做Annotation,用@interface表示。
二、元注解
@Retention 從源代碼中可以看出,主要用于提示注解要保留多長時(shí)間
package java.lang.annotation;
/**

創(chuàng)新互聯(lián)建站堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站設(shè)計(jì)、做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的啟東網(wǎng)站設(shè)計(jì)、移動媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
- 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}.
- <p>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.
- @author Joshua Bloch
- @since 1.5
- @jls 9.6.3.2 @Retention*/
@Documented
br/>*/
@Documented
br/>@Target(ElementType.ANNOTATION_TYPE)
/**
- Returns the retention policy.
- @return the retention policy
*/
RetentionPolicy value();
}
有三種取值:
RetentionPolicy.SOURCE 將會被編譯器拋棄
RetentionPolicy.CLASS 注解會被編輯器保留在類文件中,但是會被vm拋棄
RetentionPolicy.RUNTIME 注解會被編輯器保留在類文件中,也會被vm保留,所以可以通過反射讀取。
package java.lang.annotation;
/**
- Annotation retention policy. The constants of this enumerated type
- describe the various policies for retaining annotations. They are used
- in conjunction with the {@link Retention} meta-annotation type to specify
- how long annotations are to be retained.
- @author Joshua Bloch
- @since 1.5
*/
public enum RetentionPolicy {
/**
- Annotations are to be discarded by the compiler.
*/
SOURCE,
/** - Annotations are to be recorded in the class file by the compiler
- but need not be retained by the VM at run time. This is the default
- behavior.
*/
CLASS,
/** - Annotations are to be recorded in the class file by the compiler and
- retained by the VM at run time, so they may be read reflectively.
- @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
@Target 用于提示該注解使用的地方@Documented
br/>@Documented
br/>@Target(ElementType.ANNOTATION_TYPE)
/** - Returns an array of the kinds of elements an annotation type
- can be applied to.
- @return an array of the kinds of elements an annotation type
- can be applied to
*/
ElementType[] value();
}
其中ElementType的取值有下面十種:
ElementType.TYPE 用于類,接口(包括注解)或者枚舉類型
ElementType.FIELD 用于屬性字段包括枚舉常量
ElementType.METHOD 用于方法級別
ElementType.PARAMETER 用于參數(shù)聲明
ElementType.CONSTRUCTOR 用于構(gòu)造函數(shù)聲明
ElementType.LOCAL_VARIABLE 用于局部變量聲明
ElementType.ANNOTATION_TYPE 用于注解類型聲明
ElementType.PACKAGE 用于包聲明
ElementType.TYPE_PARAMETER 用于泛型聲明
ElementType.TYPE_USE 用于任意類型聲明
public enum ElementType {
/ Class, interface (including annotation type), or enum declaration */
TYPE,
/* Field declaration (includes enum constants) /
FIELD,
/Method declaration */
METHOD,
/ Formal parameter declaration */
PARAMETER,
/* Constructor declaration /
CONSTRUCTOR,
/Local variable declaration */
LOCAL_VARIABLE,
/ Annotation type declaration */
ANNOTATION_TYPE,
/* Package declaration /
PACKAGE,
/ - Type parameter declaration
- @since 1.8
*/
TYPE_PARAMETER,
/** - Use of a type
- @since 1.8
*/
TYPE_USE
}
@Documented 將注解包含在Javadoc中
package java.lang.annotation;
/**
- Indicates that annotations with a type are to be documented by javadoc
- and similar tools by default. This type should be used to annotate the
- declarations of types whose annotations affect the use of annotated
- elements by their clients. If a type declaration is annotated with
- Documented, its annotations become part of the public API
- of the annotated elements.
- @author Joshua Bloch
- @since 1.5*/
@Documented
br/>*/
@Documented
br/>@Target(ElementType.ANNOTATION_TYPE)
}
@Inherited 允許子類繼承父類
package java.lang.annotation;
/** - Indicates that an annotation type is automatically inherited. If
- an Inherited meta-annotation is present on an annotation type
- declaration, and the user queries the annotation type on a class
- declaration, and the class declaration has no annotation for this type,
- then the class's superclass will automatically be queried for the
- annotation type. This process will be repeated until an annotation for this
- type is found, or the top of the class hierarchy (Object)
- is reached. If no superclass has an annotation for this type, then
- the query will indicate that the class in question has no such annotation.
- <p>Note that this meta-annotation type has no effect if the annotated
- type is used to annotate anything other than a class. Note also
- that this meta-annotation only causes annotations to be inherited
- from superclasses; annotations on implemented interfaces have no
- effect.
- @author Joshua Bloch
- @since 1.5
- @jls 9.6.3.3 @Inherited*/
@Documented
br/>*/
@Documented
br/>@Target(ElementType.ANNOTATION_TYPE)
}
三、自定義注解的使用
創(chuàng)建一個(gè)自定義注解
import java.lang.annotation.*;
/** - Created Date: 2019/3/1
創(chuàng)建自定義注解
*/
@Target({ ElementType.METHOD, ElementType.TYPE })@Retention(RetentionPolicy.RUNTIME)
br/>@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
String value();
}
通過反射獲取注解
public class Test {
@TestAnnotation(value = "測試方法")
public static void main(String args[]){
try {
Class c=Test.class;
Method[] methods=c.getDeclaredMethods();
for(Method method:methods){
Annotation[] annotations=method.getDeclaredAnnotations();
for(Annotation annotation:annotations){
TestAnnotation testAnnotation= (TestAnnotation) annotation;
System.out.println(testAnnotation.value());
}
}
} catch (ClassNotFoundException e) {e.printStackTrace();
}
}
}
四、web開發(fā)中的運(yùn)用
在web開發(fā)中,權(quán)限控制非常重要,所以有些接口會限制必須登錄之后才能訪問,但是個(gè)別接口并沒有這種限制。一種方式是把需要過濾的ThinkMarkets代理申請www.kaifx.cn/broker/thinkmarkets.html接口或者方法配置在文件中,每次請求時(shí)在攔截器中根據(jù)請求的路徑與配置文件中的對比過濾。其實(shí)還有另外一種方式就是通過注解方式。
定義一個(gè)注解NoLogin
@Target(ElementType.METHOD)
br/>e.printStackTrace();
}
}
}
四、web開發(fā)中的運(yùn)用
在web開發(fā)中,權(quán)限控制非常重要,所以有些接口會限制必須登錄之后才能訪問,但是個(gè)別接口并沒有這種限制。一種方式是把需要過濾的ThinkMarkets代理申請www.kaifx.cn/broker/thinkmarkets.html接口或者方法配置在文件中,每次請求時(shí)在攔截器中根據(jù)請求的路徑與配置文件中的對比過濾。其實(shí)還有另外一種方式就是通過注解方式。
定義一個(gè)注解NoLogin
@Target(ElementType.METHOD)
br/>@Documented
}
標(biāo)注在方法上
在攔截器中判斷方法上是否有NoLogin注解
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
//支持兩種方式過濾 1、注解方式 添加@NoLogin注解
HandlerMethod handlerMethod= (HandlerMethod) o;
NoLogin noLogin=handlerMethod.getMethod().getDeclaredAnnotation(NoLogin.class);
if(null!=noLogin){
return true;
}
}
五、java內(nèi)置的注解
除了上述的四個(gè)元注解,java還內(nèi)置了另外三個(gè)注解:
@Override 它沒有任何的屬性,不能存儲任何其他信息。它只能作用于方法之上,編譯結(jié)束后將被丟棄。在java編譯器編譯成字節(jié)碼的時(shí)候,一旦發(fā)現(xiàn)某個(gè)方法被這個(gè)注解標(biāo)識過,就會匹配父類中是否存在同一方法,如果不存在就回編譯失敗。@Target(ElementType.METHOD)
br/>@Target(ElementType.METHOD)
public @interface Override {
}
@Deprecated 棄用的注解@Documented
br/>@Documented
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
@SuppressWarnings 壓制警告,比如某段代碼中存在過時(shí)的方法,那么在編譯過程中,會有warn警告,如果不想出現(xiàn)類似的警告,可在方法上添加這個(gè)注解。這個(gè)注解有一個(gè)value的值,這個(gè)value表示需要壓制的警告類型。
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})@Retention(RetentionPolicy.SOURCE)
br/>@Retention(RetentionPolicy.SOURCE)
/**
- The set of warnings that are to be suppressed by the compiler in the
- annotated element. Duplicate names are permitted. The second and
- successive occurrences of a name are ignored. The presence of
- unrecognized warning names is <i>not</i> an error: Compilers must
- ignore any warning names they do not recognize. They are, however,
- free to emit a warning if an annotation contains an unrecognized
- warning name.
- <p> The string {@code "unchecked"} is used to suppress
- unchecked warnings. Compiler vendors should document the
- additional warning names they support in conjunction with this
- annotation type. They are encouraged to cooperate to ensure
- that the same names work across multiple compilers.
- @return the set of warnings to be suppressed
*/
String[] value();
}
六、注解的原理
1、java.lang.annotation.Annotation中有這么一句話:The common interface extended by all annotation types 所有的注解都繼承于這個(gè)接口。怎么理解呢?其實(shí)剛才上面例子中的注解可以理解為:
public @interface TestAnnotation extends Annotation{
}
注解的本質(zhì)就是一個(gè)繼承了 Annotation 接口的接口
為了方便理解和掌握注解,還是以剛才的TestAnnotation注解為例。在idea中配置啟動參數(shù),方便查看代理產(chǎn)生的類,參數(shù)如下:
Dsun.misc.ProxyGenerator.saveGeneratedFiles=true
main方法運(yùn)行結(jié)束后,會在/com/sun/proxy目錄下生成一個(gè)代理類,反編譯之后是這樣的:
代理類proxy1重寫了TestAnnotation的所有方法,包括value()和從Annotation繼承來的equals()、hashCode()等方法。
package com.sun.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import org.fy.annotation.TestAnnotation;
public final class $Proxy1 extends Proxy implements TestAnnotation {
private static Method m1;
private static Method m2;
private static Method m4;
private static Method m0;
private static Method m3;
public $Proxy1(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final Class annotationType() throws {
try {
return (Class)super.h.invoke(this, m4, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String value() throws {
try {
return (String)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m4 = Class.forName("org.fy.annotation.TestAnnotation").getMethod("annotationType");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m3 = Class.forName("org.fy.annotation.TestAnnotation").getMethod("value");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
在看proxy1構(gòu)造函數(shù)中有一個(gè)接口InvocationHandler,這個(gè)接口的實(shí)例化對象又是誰?
java中有一個(gè)專門用于注解類型的代理對象AnnotationInvocationHandler,位于sun.reflect.annotation包中。同樣是invoke方法用于處理具體的業(yè)務(wù)。
public Object invoke(Object var1, Method var2, Object[] var3) {
String var4 = var2.getName();
Class[] var5 = var2.getParameterTypes();
if (var4.equals("equals") && var5.length == 1 && var5[0] == Object.class) {
return this.equalsImpl(var3[0]);
} else if (var5.length != 0) {
throw new AssertionError("Too many parameters for an annotation method");
} else {
byte var7 = -1;
switch(var4.hashCode()) {
case -1776922004:
if (var4.equals("toString")) {
var7 = 0;
}
break;
case 147696667:
if (var4.equals("hashCode")) {
var7 = 1;
}
break;
case 1444986633:
if (var4.equals("annotationType")) {
var7 = 2;
}
}
switch(var7) {
case 0:
return this.toStringImpl();
case 1:
return this.hashCodeImpl();
case 2:
return this.type;
default:
Object var6 = this.memberValues.get(var4);
if (var6 == null) {
throw new IncompleteAnnotationException(this.type, var4);
} else if (var6 instanceof ExceptionProxy) {
throw ((ExceptionProxy)var6).generateException();
} else {
if (var6.getClass().isArray() && Array.getLength(var6) != 0) {
var6 = this.cloneArray(var6);
}
return var6;
}
}
}
}
新聞標(biāo)題:java自定義注解的使用
轉(zhuǎn)載來于:http://www.chinadenli.net/article26/joiejg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供營銷型網(wǎng)站建設(shè)、域名注冊、網(wǎng)站排名、品牌網(wǎng)站制作、App開發(fā)、網(wǎng)站營銷
廣告
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源:
創(chuàng)新互聯(lián)