JavaSE-常用API-反射&注解&动态代理

2. 注解

2.1 定义注解

2.1.1 基本语法

  • 基本结构:

    public @interface 注解名称{
        
    }
    
  • 属性声明:

    public @interface 注解名称{
        //声明注解的属性
        public 属性类型 属性名() default 默认值;
    }
    //属性类型:基本数据类型、String、Class、注解、枚举Enum;以上类型一维数组
    //属性名:自定义
    //默认值:与类型匹配即可
    
  • 实例

    package com.czxy.d6_annotation;
    
    import java.util.Date;
    
    /** 注解定义
    
    
     */
    public @interface MyAnno {
        public String username() default "";            //字符串
        public int age() default 0;                     //基本数据类型
        public double salary() default 0;
        public Class clazz() default String.class;      //字节码对象
        public MySonAnno msa() default @MySonAnno;      //其他注解
        public MyGender mg() default MyGender.FEMALE;  //枚举
        public String[] hobbies() default {};          //一维数组
    }
    
    

2.1.2 元注解

  • 元注解:用于修饰自定义注解官方注解

    • 自定义注解:用于修饰编写类、方法等。
    • 官方注解:用于修饰自定义注解。
  • 官方注解(元注解)

    • @Target:用于确定自定义注解使用位置(类、字段、构造、方法等)
      • ElementType.TYPE 可以修饰
      • ElementType.FIELD 可以修饰字段
      • ElementType.CONSTRUCTOR 可以修饰构造
      • ElementType.METHOD 可以修饰方法
    • @Retention:自定义注解生命周期,保留的时间。
      • RetentionPolicy.SOURCE ,源码,自定义注解只能在源码中使用,字节码中没有。提供给编译器使用
      • RetentionPolicy.CLASS,字节码,自定义注解在源码字节码中使用。运行后没有。提供运行器使用。
      • RetentionPolicy.RUNTIME,运行时,自定义注解在源码字节码运行时都可以使用。开发中常见。
package com.czxy.d7_annotation2;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**

 */
@Target({ElementType.TYPE , ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.METHOD})
@Retention(RetentionPolicy.SOURCE)
public @interface MyAnno2 {
    public String value() default "";
    public String[] hobbies() default {};
}

2.2 使用注解【掌握】

2.2.1 基本语法

  • 基本使用:

    @注解名
    
  • 属性使用

    @注解名(属性名=, 属性名2=2, ...);
    //如果是一位数组,需要使用{}填写多个值
        
    
  • 实例:

    package com.czxy.d6_annotation;
    
    /** 注解使用
    
     */
    @MyAnno(username="jack",age=18,salary=10.0,clazz=String.class,msa=@MySonAnno, mg=MyGender.FEMALE, hobbies={"抽烟","喝酒","烫头"} )
    public class TestAnno {
    
        @MyAnno
        public String username = "jack";
    
        @MyAnno
        public TestAnno() {
    
        }
    
        @MyAnno
        public void info() {
    
        }
    }
    
    

2.2.2 注意实现

  • 一个目标上,同一个注解只能出现一次。
    JavaSE-常用API-反射&注解&动态代理_第1张图片
package com.czxy.d7_annotation2;

/**

 */
public @interface MyAnno2 {
    public String value() default "";
    public String[] hobbies() default {};
}

  • 属性类型为数组,值如果只有一个,{}可以省略。

    //@MyAnno2(hobbies = {"a","b"})     //标准写法
    //@MyAnno2(hobbies = "a")           //{}省略
    
  • 如果只有一对属性,且属性名为value,value可以省略

    //@MyAnno2(value = "")                //标准写法
    //@MyAnno2("")                      //只有一对,value省略
    @MyAnno2(value="", hobbies = {})    //value不能省略
    
  • 综合:

    package com.czxy.d7_annotation2;
    
    /**
    
     */
    public @interface MyAnno3 {
        public String[] value();
    }
    
    
    //@MyAnno3(value={"a"})         //标准写法
    //@MyAnno3(value="a")           //{}省略
    @MyAnno3("a")                   //value省略
    

2.3 解析注解

允许解析
JavaSE-常用API-反射&注解&动态代理_第2张图片

解析注解API
JavaSE-常用API-反射&注解&动态代理_第3张图片

  • 测试注解

    package com.czxy.d8_annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
    
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnno4 {
        public String username();
        public String password();
    }
    
    
  • 测试代码

    package com.czxy.d8_annotation;
    
    import java.lang.reflect.Method;
    
    /**
    
     */
    public class TestAnno4 {
    
        @MyAnno4(username = "jack",password = "6666")
        public void info() {
    
        }
    
        public static void main(String[] args) throws Exception {
            //1 获得方法Method
            // 1.1 获得Class
            Class clazz = Class.forName("com.czxy.d8_annotation.TestAnno4");
            // 1.2 获得Method
            Method infoMethod = clazz.getMethod("info");
    
            //2 判断Method上是否有MyAnno4注解
            boolean r = infoMethod.isAnnotationPresent(MyAnno4.class);
    
            //3 获得注解
            if(r) {
                //有
                MyAnno4 anno4 = infoMethod.getAnnotation(MyAnno4.class);
                String username = anno4.username();
                String password = anno4.password();
                System.out.println(username);
                System.out.println(password);
    
            } else {
                System.out.println("没有");
            }
        }
    
    
    
    }
    
    

2.4 模拟@Test

  • 注解

    package com.czxy.d9_annotaion4_demo;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
    
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyTest {
    }
    
    
  • 测试类

    package com.czxy.d9_annotaion4_demo;
    
    import java.lang.reflect.Method;
    
    /**
    
     */
    public class Main {
    
        @MyTest
        public void info() {
            System.out.println("----------------info");
        }
    //    @MyTest
        public void show() {
            System.out.println("-------------show");
        }
    
        public static void main(String[] args) throws Exception {
            //需求:执行当前类的被@MyTest修饰的方法,有几个执行几个!
            //info执行
    
            //1 获得class
            Class clazz = Class.forName("com.czxy.d9_annotaion4_demo.Main");
    
            //2 创建实例
            Object obj = clazz.newInstance();
    
            //3 获得所有的方法
            Method[] allMethod = clazz.getMethods();
            //4 遍历所有方法
            for(Method method: allMethod) {
                //5 判断当前方法是否有@MyTest
                boolean r = method.isAnnotationPresent(MyTest.class);
                if(r) {
                    //6 如果有,执行方法
                    method.invoke(obj);
                } else {
                    //7 如果没有,提示
    //                System.out.println(method.getName() + ",没有注解");
                }
            }
    
    
    
    
        }
    }
    
    

3. 动态代理

3.1 理论&思想

  • 代理:代理的作用,就是对目标进行增强的。
    JavaSE-常用API-反射&注解&动态代理_第4张图片

    动态代理:程序在运行时,动态创建代理类,对目标类进行代理(增强)。
    JavaSE-常用API-反射&注解&动态代理_第5张图片

3.2 代码

1)接口

package com.czxy.d10_proxy;


public interface UserService {
    public void add();
    public String update();
    public String delete();
}

2)实现类(目标类)

package com.czxy.d10_proxy;


public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("目标类UserServiceImpl.add");
    }

    @Override
    public String update() {
        System.out.println("目标类UserServiceImpl.update");
        return "update";
    }

    @Override
    public String delete() {
        System.out.println("目标类UserServiceImpl.delete");
        return "delete";
    }
}

3)测试类(代理类)

package com.czxy.d10_proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestProxy {
    public static void main(String[] args) {
        //正常使用,目标类
        UserService userService = new UserServiceImpl();
        userService.add();

        //动态代理
        //1 类加载器:每一个类都需要一个类加载器将其加载到内存中,(固定代理)
        ClassLoader classLoader = TestProxy.class.getClassLoader();
        //2 代理需要实现的所有接口
        Class[] interfaces = {UserService.class};
        //3 代理类处理类
        InvocationHandler invocationHandler = new InvocationHandler(){
            /*
                参数1:proxy,代理类
                参数2:method,代理类当前执行的方法
                参数3:args,方法的实际参数
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //方法名
                String methodName = method.getName();
                //增强
                if("delete".equals(methodName)) {
                    System.out.println("对delete进行增强");
                    return null;
                }
                //代理类中,调用目标类对应的方法
                Object result = method.invoke(userService, args);
                return result;
            }
        };
        //4 使用工具生成代理类
        UserService proxyUserService = (UserService)Proxy.newProxyInstance(classLoader,interfaces,invocationHandler);

        proxyUserService.add();
        String u = proxyUserService.update();
        System.out.println("代理类:" + u);
        String d = proxyUserService.delete();
        System.out.println("代理类:" +d);


    }
}

你可能感兴趣的:(前端,数据库,java)