Java Spring Boot VS .NetCore (八) Java 注解 vs .NetCore Attribute


 

Java Spring Boot VS .NetCore (一)來一個簡單的 Hello World

Java Spring Boot VS .NetCore (二)實現一個過濾器Filter

Java Spring Boot VS .NetCore (三)Ioc容器處理

Java Spring Boot VS .NetCore (四)數據庫操作 Spring Data JPA vs EFCore

Java Spring Boot VS .NetCore (五)MyBatis vs EFCore

Java Spring Boot VS .NetCore (六) UI thymeleaf vs cshtml

Java Spring Boot VS .NetCore (七) 配置文件

Java Spring Boot VS .NetCore (八) Java 注解 vs .NetCore Attribute

Java Spring Boot VS .NetCore (九) Spring Security vs .NetCore Security

Java Spring Boot VS .NetCore (十) Java Interceptor vs .NetCore Interceptor

Java Spring Boot VS .NetCore (十一)自定義標簽 Java Tag Freemarker VS .NetCore Tag TagHelper

繼續前面的章節,這里我介紹下注解,其實Java注解跟.NetCore的特性標簽類似,下面我們通過代碼來說明

Java自定義注解

首先我先說下Java注解需要使用的注解

@Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented

Taget:指定注解在什么地方生效,作用於什么對象上,參數很多這里把源碼拉出來了,每一個的意思就不過多介紹,一看就明白

public enum ElementType {
    /** 類、接口(包括注釋類型)或枚舉聲明 */
    TYPE,

    /** 字段聲明(包括枚舉常量) */
    FIELD,

    /** 方法聲明 */
    METHOD,

    /** 形式參數聲明 */
    PARAMETER,

    /** 構造函數聲明 */
    CONSTRUCTOR,

    /** 局部變量聲明 */
    LOCAL_VARIABLE,

    /** 注釋類型聲明 */
    ANNOTATION_TYPE,

    /** 程序包聲明 */
    PACKAGE,

    /**
     * 類型參數聲明
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * 使用類型
     *
     * @since 1.8
     */
    TYPE_USE
}
public enum RetentionPolicy {
    /**
     注解將被編譯器丟棄
     */
    SOURCE,

    /**
     注解將由編譯器記錄在類文件中,但在運行時不需要由VM保留。這是默認的行為。
     */
    CLASS,

    /**
    注解將由編譯器記錄在類文件中,並在運行時由VM保留,因此可以通過反射讀取當前注解。*/
    RUNTIME
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
/*
注解表明這個注解應該被 javadoc工具記錄
*/
}

下面就來模擬一個自定義的注解,同時簡單並模擬MyBatis中的像如下寫法,解析下面代碼的實現原理

@Select("SELECT username,email,newname,nick_name FROM user_model")
    @Results({
            @Result(property = "username",  column = "username"),
            @Result(property = "email",  column = "email"),
            @Result(property = "newname",  column = "newname"),
            @Result(property = "nickName", column = "nick_name")
    })
    List<UserModel> getAll();

這里定義一個自定義的注解接口 代碼如下,注解要作用於方法上 

Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CustomSelect {
String Sql() default "";
}

這一步也非常簡單,定義一個操作接口,使用自定義的注解,添加好相關的Sql語句

public interface ReflectorDao {

    @CustomSelect(Sql = "select * from user_model where id=1")
    int InsertModel();
}

接下來就是怎么使用了,當然這里還是要用到反射 ,這里我添加了一個測試方法,里面模擬實現了一個JDBC的操作方法

 @Test
    public  void  testReflectorDao() throws Exception {
        Class<?> c=  ReflectorDao.class;
        Method method=c.getMethod("InsertModel");
        CustomSelect  customSelect=method.getAnnotation(CustomSelect.class);
        String strsql= customSelect.Sql();
        System.out.print(strsql+"\r\n");
        //調用JDBC完成操作
        JDBCHelper.ExcuteQuery(strsql);

    }

這里反射里面的方法就不特殊說明了,這里說下 獲取注解的方法把,如下

//    // 獲取某個類型的注解
//    public <A extends Annotation> A getAnnotation(Class<A> annotationClass);
//    // 獲取所有注解(包括父類中被Inherited修飾的注解)
//    public Annotation[] getAnnotations();
//    // 獲取聲明的注解(但是不包括父類中被Inherited修飾的注解)
//    public Annotation[] getDeclaredAnnotations();
//    // 判斷某個對象上是否被某個注解進行標注
//    public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
//
//    // 獲取某個類聲明的所有字段
//    public Field[] getDeclaredFields() throws SecurityException;
//    // 獲取某個方法
//    public Method getMethod(String name, Class<?>... parameterTypes);

執行下單元測試: OK

.NetCore Attribute

Java中有的 .NetCore一樣能實現,這里就要介紹.NetCore總的特性了,就是Attribute類,怎么來使用這個呢?不要急,通過帶來是解釋,自定義的特性需要繼承Attribute類,且類名可以以Attribute結尾,這樣在使用的時候就可以通過前面的名稱來寫,代碼如下

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
    public class CustomAttribute : Attribute
    {
        public string Sql { get; set; }

    }

看到這里,就有一種熟悉感,看下源碼,這里什么Class 等等更Java用法一樣標識該特性作用於什么對象上,AllowMultiple :標識是否可以指定多次,同一個對象上多次使用特性,Inherited:當前特性是否可以被繼承

//
    // 摘要:
    //     Specifies the application elements on which it is valid to apply an attribute.
    [Flags]
    public enum AttributeTargets
    {
        //
        // 摘要:
        //     Attribute can be applied to an assembly.
        Assembly = 1,
        //
        // 摘要:
        //     Attribute can be applied to a module.
        Module = 2,
        //
        // 摘要:
        //     Attribute can be applied to a class.
        Class = 4,
        //
        // 摘要:
        //     Attribute can be applied to a structure; that is, a value type.
        Struct = 8,
        //
        // 摘要:
        //     Attribute can be applied to an enumeration.
        Enum = 16,
        //
        // 摘要:
        //     Attribute can be applied to a constructor.
        Constructor = 32,
        //
        // 摘要:
        //     Attribute can be applied to a method.
        Method = 64,
        //
        // 摘要:
        //     Attribute can be applied to a property.
        Property = 128,
        //
        // 摘要:
        //     Attribute can be applied to a field.
        Field = 256,
        //
        // 摘要:
        //     Attribute can be applied to an event.
        Event = 512,
        //
        // 摘要:
        //     Attribute can be applied to an interface.
        Interface = 1024,
        //
        // 摘要:
        //     Attribute can be applied to a parameter.
        Parameter = 2048,
        //
        // 摘要:
        //     Attribute can be applied to a delegate.
        Delegate = 4096,
        //
        // 摘要:
        //     Attribute can be applied to a return value.
        ReturnValue = 8192,
        //
        // 摘要:
        //     Attribute can be applied to a generic parameter.
        GenericParameter = 16384,
        //
        // 摘要:
        //     Attribute can be applied to any application element.
        All = 32767
    }

下面我們同樣用接口來實現,代碼如下,前面說了 自定義屬性已Attribute結尾的類名,寫的時候直接寫Custom

public interface RelactorDao
    {

        [Custom(Sql = "select * from user_model where id=1")]
        void InsertModel();

    }

這里我寫一個測試類是看下,由於時間的關系,這里就不寫SqlHelper 來執行了,輸入下Sql就行了,這個跟Java一樣需要使用反射,思想一樣,只是使用方法名稱不同而已,具體的方法就不做介紹..有興趣自己了解下

  public class TestClass
    {
        public void TestMethod()
        {
            var type = typeof(RelactorDao);
            MethodInfo methodInfo= type.GetMethod("InsertModel");
            var atrrs = methodInfo.GetCustomAttributes(typeof(CustomAttribute), false) as CustomAttribute[];
            var strSql = atrrs.First().Sql;
            //當然這里也可以執行
            Console.WriteLine(strSql);
        }
    }

接下來我們在看下執行效果 OK

 

 總結

這里只是簡單的模擬下,其實要實現MyBatis中的注解的功能,其實還需要其他的知識,面向切面編程的技術AOP

Java中的 @Aspect 注解 ,.NetCore 可以通過動態代理來實現,但是反過來想下,.NetCore中一樣可以實現類似於MyBait一樣使用方式的ORM框架,可能.NetCore中考慮到大量應用反射會導致性能問題

 

 

 

 

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM