2.2 注解与动态代理

2.2 注解与动态代理

注解

  • 是一种代码级别的说明
  • 注解是写给计算机看的
  • 作用:
    • 编译检查:通过代码标志注解,让编译器实现基本的编译检测
    • 代码分析
    • 编写文档

注解类型

JDK提供的注解

  • Deprecated :被修饰方法已经过时,不建议但仍然可以使用,效果为对应方法被划除
  • Override: 重写方法
  • SuppressWarnings(value={选项1,选项2}): 关闭警告,被修饰的类或方法如果存在编译警告,将被编译器忽略
    • deprecation:忽略过时
    • rawtypes:忽略类群安全
    • unused:忽略不使用
    • unchecked:忽略安全检查,执行了未检查的转换时的警告
    • serial:当在可序列化的类上缺少serialVersionUID定义时的警告
    • finally:任何finally子句不能正常完成时的警告
    • null:忽略空指针
    • fallthrough:switch直接通往下一种情况而没有break时的警告
    • all:忽略所有

元注解

  • 自定义注解需要使用元注解进行修饰才能真正的使用
  • 定义:用于修饰注解的注解
  • 元注解
    • @Retention:确定被修饰的自定义注解生命周期

      • ReteentionPolicy.SOURCE:只能存在源码中,class没有,用途:提供给编译器使用
      • ReteentionPolicy.CLASS:运行时内存没有,默认行为,用途:提供给虚拟机使用
      • ReteentionPolicy.RUNTIME:存在于源码、字节码、虚拟机,用途:取代xml配置
    • @Target:确定自定义注解的使用位置

      • ElementType.TYPE:修饰类、接口
      • ElementType.FIELD
      • ElementType.METHOD
      • ElementType.PARAMTER
      • ElementType.TYPE_PARAMTER
      • ElementType.CONSTRUCTOR:修饰构造
      • ElementType.LOCAL_VARIABLE
      • ElementType.PACKAGE
      • ElementType.MODULE
      • ElementType.TYPE_USE
    • @Documented:使用javaDoc生成api文档时是否包含此注解,默认情况下注解是不会出现在javadoc中的

    • @Inherited:如果父类使用被修饰的注解,子类是否继承

jdk7以后添加的注解

  • SafeVarargs:忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告
  • FunctionalInterface:jdk8后添加,标志一个匿名函数或函数式接口
  • Repeatable:jdk8后开始支持,标志某注解可以在同一个声明上使用多次

自定义注解

  • 使用关键字@interface
    • 和implemented实现接口不同,annotation接口的实现细节都由编译器完成,并且定义的注解不能继承其他的注解或接口
    1. 定义类
    2. 定义接口
    3. 定义枚举
    @元注解
    @interface MyAnnol{
      public|abstract String username() []default "defaultName"] ;
    }
    //使用
    @MyAnnol(
      username = ...;
      )
    public class TestAnno{}
    
  • 属性修饰符:默认且只能是public abstract
  • 注意
    • 注解可以没有属性,有属性用()
    • 多个属性用逗号分隔
    • 属性名为vale且当前只有一个属性,value可以省略,否则不能省略
    • 属性为数组,内容格式为{1,2,3}
    • 属性类型为数组,值只有一个时{}可以省略
    • 一个对象只能使用一次(同一个)注解,

Annotation架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PasMbagC-1585648435991)(:storage\b1247d0d-115a-4161-9fd2-ccc8bb2433e0\359acde4.png)]

  • Annotation
    package java.lang.annotation;
    public interface Annotation {
    
        boolean equals(Object obj);
    
        int hashCode();
    
        String toString();
    
        Class<? extends Annotation> annotationType();
    }
    

注解解析

  • 获取注解上设置的数据
  • 使用java.lang.reflect.AnnotatedElement
  • 方法
    • boolean isAnnotationPresent(Class AnnotationClass):判断是否有注解
    • T getAnnotation(class<T> annotationClass):获取指定的注解
    • Annotation[] getAnnotaions():获取对象及其从父类上继承的所有的注解
    • Annotation[] getDeclaredAnnotaions():获取对象的所有的注解

代理

静态代理

  • 创建一个接口
  • 然后创建被代理的类实现该接口并实现该接口的抽象方法,
  • 创建一个代理类,同时实现这个接口
    //接口
    public interface HelloInterface{
      void sayHello();
    }
    //被代理类
    public class hello implements HelloInterface{
      @Override
      public void sayHello(){
        op;
      }
    }
    
    //代理类
    public class proxy implements HelloInterface{
      private HelloInterface hello = new Hello();
      @Override
      public void sayHello(){
        ...
        hello.sayHello();
        ...
      }
    }
    //使用代理类
    proxy pr=new proxy();
    pr.sayHello();
    
  • 静态代理只能为一个类服务,且事先知道被代理类

动态代理

  • 不用手动编写一个代理对象,不需要一一编写与目标对象相同的方法,这个过程,在运行时的内存中动态生成代理对象

Proxy API

newProxyInstance(ClassLoader loader, Class\<?>[] interfaces, InvocationHandler h)

  • loader:ClassName.class.getClassLoader()
  • interfaces:需要实现的所有类
    1. 目标类实例.getClass().getInterfaces()(只能获得自己的接口)
    2. new Class[] {UserService.class}
  • h:处理类、接口,必须进行实现类
    • 重写invoke(onject proxy,Method method,Object[] args),代理类的每一个方法执行时,都将调用一次invoke
      • 参数1:代理对象
      • 参数2:代理对象当前执行方法的描述对象
        • 执行方法名:method.getName()
        • 执行方法:method.invoke(对象,实际参数)
      • 参数3:方法实际参数
      List<String> proxyInstance = (
            List<String>)Proxy.newProxyInstance(list.getClass().getClassLoader(),
            list.getClass().getInterfaces(),
            new InvocationHandler() { 
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return method.invoke(list, args);
                }
            });
     proxyInstance.add("你好");
     System.out.println(list);
    
  • 动态代理底层实现
    • 通过实现InvocationHandler接口实现自己的调用处理器
    • 通过proxy类指定classloader对象和一组接口来创建动态代理类
    • 通过反射获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型
    • 通过构造函数创建动态代理类实例
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值