java 自定义注解

注解:

提示:本文属于基础语法和例子,个人复习整理,用于备忘,谢谢!!!!

简介:

注解就是给程序添加一个字符@开头的标记,可以标记接口,类,方法、字段,方法参数,构造方法等。注解可以被编译器、程序运行时和其它工具使用,用于增加或修改程序行为等。

元注解:

(1)@Target:

注解的目标

属性(枚举类 )说明
ElementType.TYPE表示类、接口(包括注解),或者枚举说明
ElementType.FIELD字段,包括枚举常量
ElementType.METHOD方法
ElementType .PARAMETER方法中的参数
ElementType.CONSTRUCTOR构造方法
ElementType .LOCAL_VARIABLE本地变量
ElementType.MODULE模块(Java 9 引入)

(2)@Retenion:

保留范围,如果没有声明@Retention,则默认为时Class

属性(枚举类)说明
RetentionPolicy.SOURCE只在源码总中保留,编译器编译后就会丢掉
RetentionPolicy. CLASS保存到字节码文件中,但Java虚拟机将class文件加载到内存不一定会在内存中保留
RetentionPolicy.RUNTIME一直保留到运行时

(3) @Documented:

表示注解信息包含到生成的文档中。

(4)@Inherited:

继承注解,表示子类继承父类的时候也会把父类带有@Inherited元注解声明的自定义注解给继承下来。

示例:

/**
 * 自定义注解
 * @Target 表示注解用于的目标,可以多个,ElementType是枚举,主要可选值有:
 * .TYPE: 表示类、接口(包括注解),或者枚举声明
 * .FIELD: 字段,包括枚举常量
 * .METHOD: 方法
 * .PARAMETER: 方法中的参数;
 * .CONSTRUCTOR: 构造方法
 * .LOCAL_VARIABLE:本地变量
 * .MODULE: 模块(Java 9引入的)
 *
 * @Retention 表示注解信息保留到什么时候,取值只能一个,类型为RetentionPolicy,是一个枚举,可选值有:
 * .SOURCE:只在源代码中保留,编译器将代码编译为字节码文件后就会丢掉
 * .CLASS:保留到字节码文件中,但Java虚拟机将class文件加载到内存时不一定会在内存中保留
 * .RUNTIME:一直保留到运行时
 * 如果没有Retention,则默认为CLASS
 *
 * @Documented 表示注解信息包含到生成的文档中
 *
 * @Inherited 表示继承的元注解,当这个注解加上时,加到某个类上时,这个注解类的子类会继承父类的注解
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MineCustomize{
   String name() default "";
}

查看注解信息:

反射中和注解相关的方法如下:

方法返回值说明
getAnnotations()Annotation []获取所有注解
getDeclaredAnnotations()Annotation []获取所有本元素上直接声明的元素,忽略@Inherited 来的
getAnnotation(Class annotationClass)A获取指定类型的注解,没有返回null
isAnnotationPresent(Class<? extends Annotation>)boolean判断是否有指定注解

注解应用示例:简易DI容器

/**
 * 表示依赖关系的注解
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SimpleInject {
}


/**
 * 标记类为单列类
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SimpleSingleton {
}

package annotation;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 注解和反射来做一个简单的DI容器
 */

public class AnnoDiContaniner {

    //静态注册表
    private static Map<Class<?>,Object> instances = new ConcurrentHashMap<>();

    //获取实例
    public static <T> T getInstance(Class<T> cls){
        Object obj = null;
       try{
           //判断该对象是否有有单例注解
           Boolean simpleSingleton = cls.isAnnotationPresent(SimpleSingleton.class);
           //如果没有单例注解则直接创建新对象
           if(!simpleSingleton){
               return createInstance(cls);
           }
           //从静态单例注册表里取对象
           obj = instances.get(cls);
           //如果取的对象不为null,直接返回
           if(obj != null){
               return (T) obj;
           }
           synchronized (cls){
               //如果对象为空,生成新对象,并放入注册表里
               if(obj == null){
                   obj = createInstance(cls);
                   instances.put(cls,obj);
               }
           }
       }catch (Exception e){
           e.printStackTrace();
       }
        return (T)obj;
    }

    //创建实例
    public static <T> T createInstance(Class<T> cls) throws Exception{
        //创建对象
        T obj = cls.newInstance();
        //获取该类的所有属性
        Field [] fields = cls.getDeclaredFields();
        for (Field field:fields) {
            //判断该属性上是否包含依赖注解
            if(field.isAnnotationPresent(SimpleInject.class)){
                //判断该属性是否有读写权限
                if(!field.isAccessible()){
                    //设置属性的读写权限为true
                    field.setAccessible(true);
                }
                //获取属性类型
                Class<?> fieldCls = field.getType();
                //设置属性值
                field.set(obj,getInstance(fieldCls));
            }
        }
        return obj;
    }

    static class ServiceA{
        @SimpleInject
        private ServiceB serviceB;

        public void callB(){
            serviceB.action();
        }
    }

    @SimpleSingleton
    static class ServiceB{
       public void action(){
           System.out.println(" I'm B");
       }
    }

    public static void main(String[] args) {
        ServiceA serviceA = getInstance(ServiceA.class);
        serviceA.callB();
    }

}

总结:

注解提升了Java 语言的表达能力,有效的实现了应用功能和底层功能的分离,框架/库的程序员可以专注于底层实现,借助注解实现通用的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值