Java 注解 基础

注解篇

如今的开发,愈来愈多的使用到注解简化开发,好比spring_boot、spring_cloud中的一系列注解,这就让我很是感兴趣的事情java

接触spring原始开发并很少,也知道前期spring开发会带来一大堆xml的配置,由于在下仍是比较渣的coder面试

我也在面试过程当中常常被问spring的特性什么什么的,像我这样从spring_boot往回走的人很少吧,不理解注解都很差意思说spring,mybatis也是spring

 

好处

①学习注解可以读懂别人写的代码,特别是框架相关的代码,在学习或工做中会去看别人的代码,不少知识是和注解相关的引用体现,很差好研究一下就不能很顺畅的看懂其代码套路编程

②让咱们注解编程更加简洁,代码更加清晰,趋向于programmer的进阶,engineer的方向前进,能够将不少逻辑才能实现的方法转化成一个注解来替代,来一套让本身飞起来的服务数组

③让本身的逼格别具特点,让别人也向你学习session

 

你们都会使用注解,但不必定都会自定义注解来解决问题,开始学习mybatis

 

概念

Java提供了一种原程序中的元素关联任何信息和任何元数据的途径和方法app

就像学校里起步学Java时就教面向对面的概念,比较抽象,须要在后面的编程学习或工做中才能慢慢领悟的方式学习---知新而温故框架

 

解析注解

★Java中的常见注解ide

① JDK常见注解: @Override@Deprecated 、@Suppvisewarnings等

建立一个接口和一个实现类

public interface Dog {
    String kind();
    Integer age();
    void work();
}
public class SingleDog implements Dog {
    @Override
    public String kind() {return null;}
    @Override
    public Integer age() {return null;}
    @Override
    public void work() {}
}

@Override出现,覆盖父类的方法,能够发现若是将接口的方法注掉,标@Override的实现方法就会出现问题

 

每只Dog都有品种,年龄,但不是每只Dog都能work,因此决定将此方法做废,使用@Deprecated注解

public interface Dog {
    String kind();
    Integer age();
    @Deprecated
    void work();
}

此时实现的方法不会出现什么问题,在调用的时候就会出现提示信息,以下:

public class DemoMain {
    public static void main(String[] args) {
        Dog dog=new SingleDog();
        dog.kind();
        dog.age();
        dog.work();
    }
}

有的编程工具还会出现警告,也有某些编程洁癖的公司是不容许出现警告和此类问题

 

在方法上加@Suppvisewarnings注解,就能够去除警告和删除线

public class DemoMain {
    @SuppressWarnings("deprecation")
    public static void main(String[] args) {
        Dog dog=new SingleDog();
        dog.kind();
        dog.age();
        dog.work();
    }
}

 

② 第三方注解

Spring常见注解: @Autowired 、@Service 、@Repository等

Mybatis常见注解: @InsertProvider 、@Select 、 @Options等

下面以@Autowired示例,对比引入先后的展现效果: 

》类的实现

public class DogManagerImpl implements DogMapper {
    private DogDao dogDao;

    public void setDogDao(DogDao dogDao) {
        this.dogDao = dogDao;
    }
    //...
}

配置文件

<bean id="DogManagerImpl" class ="com.cloud.eureka.demo.DogManager">
    <property name="dogDao" ref="dogDao" />
</bean>
<bean id="dogDao" class ="com.cloud.eureka.demo.DogManagerImpl">
    <property name="sessionFactory" ref="mySessionFactory" />
</bean>

 

》引入@Autowired

public class DogManagerImpl implements DogMapper {
    @Autowired
    private DogDao dogDao;
    //...
}

两种引入对比,我这么懒的人,确定用@Autowired

 

★注解的分类

①按运行机制分

  • 源码注解: 只在源码中存在,编译成class文件时就不存在
  • 编译时注解: 在源码和class文件中都存在,例如@Override 、@Deprecated等,好比Override在编译时告诉编译器,这个子类方法是覆盖父类的方法;若是实现,没有覆盖,那么代码上就会报错
  • 运行时注解: 在运行时起做用,能够影响运行逻辑,例如@Autowired

②按来源分

  • 来自JDK的注解
  • 来自第三方的注解 : 这个使用的最多
  • 自定义的注解

③元注解

  • 给注解的注解

 

★自定义注解

》自定义的语法要求 》注解的注解(元注解)

import java.lang.annotation.*;

//@Target、@Retention、@Inherited、@Documented 为元注解
@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
//以public @interface关键字定义注解
public @interface MyAnnotation {
    //成员的类型有规范,包括基本类型、String、Class、Annotation、Enumeration
    //成员大部分使用基本类型、Enumeration以及String,其余的比较少见
    //成员不能够List、Map、对象等类型
    //没有成员的注解称为标识注解

    //成员以无参数、无异常方式声明
    String hello();

    //若是注解只有一个成员,则成员的名字必须为value,此处的必须是一个规范
    //若是MyAnnotation只有一个成员,那么使用的方式@MyAnnotation("val")
    //正常使用方式@MyAnnotation(value="val")
    String value();

    //能够为成员指定一个默认值default
    int age() default 21;
}

 

@Target 定义一个注解的做用域,其有一个成员ElementType[] value();是一个枚举数组

ElementType常量提供简答的分类,经常使用于@Target元注释用于指定编写注释的合法位置,给定类型

/** 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 */
TYPE_PARAMETER,

/** Use of a type */
TYPE_USE

@Retention(RetentionPolicy.RUNTIME)注解定义运行机制,声明生命周期类型 SOURCE, CLASS, RUNTIME

@Inherrited注解容许子类继承

@Documented生成javadoc时会包含注解信息,标识注解

 

》使用自定义注解

@MyAnnotation(hello = "tom",value = "val",age = 18)
public String demo(){
   return "demo";
}

 

★解析注解

概念: 经过反射获取类、函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑

下面定义一个注解,经过反射解析注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation {
    String value();
}
public interface Dog {
    String kind();
    
    String name();
    
    void work();
}
@MyAnnotation("这是实现类")
public class DogImpl implements Dog {
    @Override
    @MyAnnotation("这是kind方法")
    public String kind() {return null;}

    @Override
    public String name() {
        return null;
    }

    @Override
    public void work() {}
}
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class ParseAnnotation {
    public static void main(String[] args) throws ClassNotFoundException {
        //1.类加载器
        Class c = Class.forName("com.cloud.eureka.demo.DogImpl");

        //2.找到类上的注解
        boolean b = c.isAnnotationPresent(MyAnnotation.class);

        if (b) {
            //3.获取注解示例
            MyAnnotation annotation = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
            System.out.println("3。" + annotation.value());
        }

        System.out.println("-------------------------------");

        //4.找到方法上的注解
        Method[] methods = c.getMethods();
        for (Method method : methods) {
            boolean mb = method.isAnnotationPresent(MyAnnotation.class);
            if (mb) {
                //5.获取注解示例
                MyAnnotation annotation = (MyAnnotation) method.getAnnotation(MyAnnotation.class);
                System.out.println("5。" + annotation.value());
            }
        }

        System.out.println("-------------------------------");

        //6.获取方法的注解
        for (Method method : methods) {
            Annotation[] annotations = method.getAnnotations();
            for (Annotation annotation : annotations) {
                if (annotation instanceof MyAnnotation) {
                    MyAnnotation myAnnotation = (MyAnnotation) annotation;
                    System.out.println("6。" + myAnnotation.value());
                }
            }
        }
    }
}

控制台输出:

 

将MyAnnotation注解的元注解@Retention改为@Retention(RetentionPolicy.SOURCE),就会反射不到,由于这个做用域只在源码级别存在,编译运行就不存在了; 元注解@Retention改为@Retention(RetentionPolicy.CLASS),运行结构控制台依然是空的,执行的main是运行时的环境,只能是运行时注解@Retention(RetentionPolicy.RUNTIME)

 

提示: @Inherited元注解在接口实现时是无效的,是类与类的继承才会有效果,而且只会继承类上的注解信息,不会继承方法上的注解

------------------------------------------------------------------

相关文章
相关标签/搜索