【Java】反射、注解、动态代理总结(二)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 【Java】反射、注解、动态代理总结

09_反射:方法调用


目标

  • 能够使用Method对象执行方法 【掌握】

路径

  1. 案例:调用无参无返回值的方法
  2. 案例:调用有参有返回值的方法
  3. 案例:调用私有方法
  4. 案例:调用静态方法

案例:调用无参无返回值的方法

 @Test
    public void testMethod1() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class stuClass = Student.class;
        //因为在调用Method时,需要传递Student对象
        Constructor con = stuClass.getConstructor();
        Student stu = (Student)con.newInstance();
        //获取public void study()方法的对象
        Method method = stuClass.getMethod("study");
        //使用Method对象 执行study()方法
        method.invoke( stu );
    }

案例:调用有参有返回值的方法

 //有参有返回值
    @Test
    public void testMethod2() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class stuClass = Student.class;
        //因为在调用Method时,需要传递Student对象
        Constructor con = stuClass.getConstructor();
        Student stu = (Student)con.newInstance();
        //获取public String sayHello(String name)方法的Method对象
        Method method = stuClass.getMethod("sayHello", String.class);
        //调用method方法
       Object result = method.invoke(stu,"波波");
        System.out.println(result);
    }

案例:调用私有方法

//私有方法
    @Test
    public void testMethod3() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException {
        //获取Class对象
        Class stuClass = Student.class;
        //因为在调用Method时,需要传递Student对象
        Constructor con = stuClass.getConstructor();
        Student stu = (Student)con.newInstance();
        //获取 private void eat(String name)方法的Method对象
        Method method = stuClass.getDeclaredMethod("eat", String.class);
        //去除JVM对当前次权限的检查
        method.setAccessible(true);
        //执行method方法
        method.invoke(stu,"红烧肉");
    }

案例:调用静态方法

//静态方法
    @Test
    public void testMethod4() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //获取Class对象
        Class stuClass = Student.class;
        //静态方法的调用不需要对象。"类名.静态方法()"
        //获取public static void sleep()方法的Method对象
        Method method = stuClass.getMethod("sleep");
        //执行静态方法
        method.invoke(null);//不需要传递对象(null就表示执行静态方法)
    }

小结

Method对象的使用步骤:

1、获取Class对象

2、基于Class对象,获取Method对象

//有参方法
Method method = Class对象.getMethod("方法名",参数1类型.class,参数2类型.class ...);
//无参方法
Method method = class对象.getMethod("方法名");

3、使用Method对象,执行方法

//调用非静态方法
method对象.invoke(实例对象,方法中需要的实参)
//调用静态方法
method对象.invoke(null,方法中需要的实参)    

反射的作用案例演示

  • 作用
    反射是框架的灵魂!框架的底层一定会用到反射技术。
  • 需求:要把猫的睡觉方法 变成 狗的吃饭方法
  • 效果:使用反射+Properties完成配置文件。把需要修改的灵活的内容写在配置文件中,代码不需要做任何的改动。
  • 案例演示
public class Dog {
    public void eat(){
        System.out.println("狗爱吃肉");
    }
    public void sleep(){
        System.out.println("狗睡觉流口水");
    }
}
public class Cat {
    public void eat(){
        System.out.println("猫爱吃鱼");
    }
    public void sleep(){
        System.out.println("猫睡觉打呼噜");
    }
}
  public class Demo {
      public static void main(String[] args) throws Exception{
          //不使用反射
          //需求:   要把猫的睡觉方法  变成  狗的吃饭方法
          //Dog d = new Dog();
          //d.eat();
          //使用反射
          //properties
          Properties pro = new Properties();
          //load():可以把文件中的键值对读取到集合中
          FileReader fr = new FileReader("day21\\aaa.txt");
          pro.load(fr);
          //通过键获取值
          String cn = pro.getProperty("className");
          String mn = pro.getProperty("methodName");
          //获取字节码对象
          Class c = Class.forName(cn);
          //获取空参构造
          Constructor con = c.getConstructor();
          //执行构造方法
          Object o = con.newInstance();
          //获取方法
          Method m = c.getMethod(mn);
          //执行方法
          m.invoke(o);
      }
  }
  配置文件:
    className=com.itheima_05.Cat
    methodName=sleep

10_注解:概述


目标

  • 能够理解注解在程序中的作用 【了解】

路径

  1. 什么是注解
  2. 注解的作用

注解

什么是注解?

注解(Annotation)也称为元数据,是一种代码级别的说明

注解是JDK1.5版本引入的一个特性,和类、接口是在同一个层次

注解可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明

注解:就是具有特殊含义的标记(注解是给机器阅读的)

注解的作用

注解就是在代码里添加一些特殊标志,这些标志可以在编译,类加载,运行时被读取,并执行相应的处理,以便于其他工具补充信息或者进行操作

注解的作用:

  1. 编译检查
  • @Override:用来修饰方法声明。
  • 用来告诉编译器该方法是重写父类中的方法,如果父类不存在该方法,则编译失败
  1. 代码分析:
  • 通过代码里标识的注解对代码进行分析
  • 框架的配置( 框架 = 代码 + 配置 )
  • 具体使用请关注框架课程的内容的学习(注解去配置数据)
  • 生成帮助文档
  • @author:用来标识作者姓名
  • @version:用于标识对象的版本号,适用范围:文件、类、方法
  • 使用@author和@version注解就是告诉Javadoc工具在生成帮助文档时把作者姓名和版本号也标记在文档中

使用过的注解:

  • @Override
  • 用来修饰方法声明,告诉编译器该方法是重写父类中的方法,如果父类不存在该方法,则编译失败
  • @Test
  • Junit测试注解
  • @FunctionalInterface //函数式接口
  • 小结

注解:在代码中添加的标记,JVM看到注解标记后会执行一些操作

注解的作用:

  • 编译检查
  • 运行时代码分析
  • 生成文档

11_注解:自定义注解


目标

  • 能够熟悉自定义注解的格式 【会用】

路径

  1. 注解的定义格式
  2. 定义带有属性的注解

注解的定义格式

定义注解使用关键字:@interface

public @interface 注解名{
   //内容
}

注解本质上就是一个接口。所有注解都会继承一个接口:Annotation

public interface 自定义注解名 extends java.lang.annotation.Annotation {}

带有属性的注解

  1. 属性的格式
  • 格式1:数据类型 属性名(); //无默认值的属性
  • 格式2:数据类型 属性名() default 默认值; //有默认值的属性
  1. 属性定义示例
public @interface Student {
  String name();                // 姓名
  int age() default 18;         // 年龄
  String gender() default "男"; // 性别
} 
// 该注解就有了三个属性:name,age,gender

小结

注解的定义格式:

public @interface 注解名
{
    //属性格式 :  数据类型 属性名()
    String 属性名();
    int 属性名() default 默认值;
}
//注意:属性的类型只能是8种基本数据类型、String、Class、枚举、注解、(以及一维数组形式)

12_注解:注解的使用


目标

  • 能够掌握注解的基本使用 【会用】

路径

  1. 注解的使用格式
  2. 案例代码
  3. 特殊属性value

注解的使用格式

格式:

//无属性注解
@注解名                      例:@Test
//有属性注解
@注解名(属性=值,属性=值)

注解可以在类上,成员变量上,构造方法上,方法上,参数上…

有默认值的属性,可以不用进行赋值。

案例代码

将Book注解使用起来

public @interface Book {
    String name();
    double price() default 100.0;
    String[] author();
}

建立一个BookStore的类,在类中定义成员变量,构造方法,成员方法

@Book(name = "西游记", author = {"吴承恩", "张三"})
public class BookStore {
    @Book(name = "三国", price = 10, author = {"罗贯中"})
    private String book;
    @Book(name = "三国", price = 10, author = {"罗贯中"})
    public BookStore() {
    }
    @Book(name = "三国", price = 10, author = {"罗贯中"})
    public void test() {
    }
}

特殊属性value

如果注解中只有一个属性要赋值,而且名字是value,可以将value给省略,可以直接给值

@interface A{
    String value();
}
@interface B{
    String value();
    String name();
}
@interface C{
    String value();
    int price() default 100; //有默认值
}
//测试类
public class Demo {
    @A("值")  //当自定义注解中仅有一个value属性时,可以省略value属性名
    public void test1() {
    }
    @B(value = "值",name="aa") //当自定义注解中除了value属性外,还有其它属性,value不能省略
    public void test2() {
    }
    @C("值")//自定义注解中除了value属性外,还有其它带有默认值的属性,value可以省略
    public void test3() {
    }
}

小结

自定义注解:

public @interface Book{
    //属性
    String name();
    double price() default 100;
}

在程序代码中使用自定义注解:

//注解可以应用在:类、方法、变量、构造方法
@Book(name="属性值")  //price属性使用默认值
public class BookStore{
    @Book(name="属性值",price="新的值") //新的price值,会覆盖默认值
    public void method(){
    }
}
    1.如果自定义注解中的属性不给默认值,那么使用的时候必须赋值,如果有默认值,使用的时候可以不给值
    2.使用注解:@注解名(属性名=属性值,属性名=属性值,....)
    3.如果注解中没有属性,使用的时候@注解名
    4.如果属性是数组,那么赋值方式:
        @注解名(属性名=属性值,属性名=属性值,属性名={属性值,属性值,..}....)
    5.如果属性是数组类型,并且使用的时候只给一个值,那么可以省略大括号
    6.如果属性只有一个并且属性名是value,那么给value赋值的时候可以不写value
    7.如果含有多个属性,并且没有默认值,那么给value赋值的时候必须书写value
    8.如果含有多个属性,并且具有默认值,那么给value赋值的时候可以不写value********************
    9.同一个注解不能同时修饰同一个方法或者同一个类
    10.不同注解可以同时修饰同一个方法或者同一个类

13_注解:元注解


目标

  • 熟悉Target和Retention两个元注解的作用 【会用】

路径

  1. 元注解的作用
  2. 常用的元注解
  3. 元注解的使用

元注解的作用

默认情况下,注解可以用在任何地方,比如类,成员方法,构造方法,成员变量等地方

如果要限制自定义注解的使用位置怎么办?那就要学习一个新的知识点:元注解

结论:元注解是用来约束自定义注解的使用范围、生命周期

常用的元注解

常用元注解:@Target、@Retention

@Target

  • 作用:指明此注解用在哪个位置,如果不写默认是任何地方都可以使用
  • @Target可选的参数值在枚举类ElemenetType中包括:
  • TYPE: 用在类,接口上
  • FIELD:用在成员变量上
  • METHOD: 用在方法上
  • PARAMETER:用在参数上
  • CONSTRUCTOR:用在构造方法上
  • LOCAL_VARIABLE:用在局部变量上
  • @Retention
  • 作用:定义该注解的生命周期(有效范围)。
  • @Retention可选的参数值在枚举类型RetentionPolicy中包括:
  • SOURCE:注解只存在于Java源代码中,编译生成的字节码文件中就不存在了
  • 使用场景:针对一些检查性的操作,比如:@Override ,就使用SOURCE注解
  • CLASS:注解存在于Java源代码、编译以后的字节码文件中,运行的时候内存中没有,默认值
  • 使用场景:在编译时进行一些预处理操作,比如:生成一些辅助代码,就用CLASS注解

RUNTIME:注解存在于Java源代码中、编译以后的字节码文件中、运行时内存中,程序可以通过反射获取该注解

使用场景:要在运行时去动态获取注解信息,那只能用 RUNTIME 注解

元注解的使用

@Target({ElementType.METHOD,ElementType.TYPE}) //元注解
@interface Stu{
    String name();
}
//类
@Stu(name="jack")  //成功
public class AnnotationDemo02 {
    // 成员变量
    @Stu(name = "lily")  // 编译失败
    private String gender;
    // 成员方法
    @Stu(name="rose")  //成功
    public void  test(){
    }
    // 构造方法
    @Stu(name="lucy") // 编译失败
    public AnnotationDemo02(){}
}

小结

元注解的作用:

  • 限定自定义注解的使用范围、生命周期
  • 限制使用范围:@Target
  • 限定生命周期:@Retention

14_注解:注解解析


目标

  • 能够使用反射的技术完成注解数据的解析 【会用】

路径

  1. 获取注解数据的原理
  2. 案例代码

获取注解数据的原理

想要对注解中的数据进行解析,需要借助:AnnotatedElement接口

  • Field,Method,Constructor,Class等类都是实现了AnnotatedElement接口

AnnotatedElement 是一个接口,定义了解析注解的方法:

1. boolean isAnnotationPresent(Class<Annotation> annotationClass)   
   判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false
   public class BookStore{
       @Book(name="书名")
       public void buy() // Method对象 判断该对象上是否使用了@Book注解
       {                 // boolean flag = Method对象.isAnnotationPresent(Book.class)
       }
   } 
2. T getAnnotation(Class<T> annotationClass) 
   根据注解类型获得对应注解对象
   // 获取对象上的自定义注解
   // Book bookAnno = Method对象.getAnnotation(Book.class); 
   //      bookAnno.属性   //获取注解中属性的值

Class,Constructor,Method,Field都会实现AnnotatedElement 接口

  • 解析类型上的注解:借助字节码对象(Class对象)
  • 解析构造方法上的注解:借助构造器对象(Constructor对象)
  • 解析方法上的注解:借助方法对象(Method对象)
  • 解析字段上的注解:借助字段对象(Field对象)

注解解析的步骤:(注解是书写在:类、方法、变量上)

1、利用反射技术获取注解作用的对象:类、方法、变量、构造方法

2、判断对象上是否有自定义注解存在

3、有:获取对象上的自定义注解

4、使用获取到的自定义注解对象,拿到注解中的属性值

注意:注解解析必须保证自定义注解生命周期在RUNTIME(程序运行中)

案例代码

需求如下:

  1. 定义注解Book,要求如下:
  2. 注意:注解解析必须保证自定义注解生命周期在RUNTIME(程序运行中)

案例代码

需求如下:

  1. 定义注解Book,要求如下:
  2. 定义BookStore类,在类和成员方法上使用Book注解
  3. 定义TestAnnotation测试类获取Book注解上的数据
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD,ElementType.TYPE}) //使用范围:方法、类
@Retention(RetentionPolicy.RUNTIME) //保证注解在程序执行时有效(适用于注解解析)
public @interface Book {
    String value();
    double price() default 100;
    String[] authors();
}
//类
public class BookStore {
    @Book(value = "Java入门", authors = {"张老师", "毕老师"})
    public void buy() {
        System.out.println("购书.....");
    }
}
//对注解中的数据进行解析
public class TestBookStore {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //反射套路:1、Class  2、构造器   3、Method
        Class<BookStore> bookStoreClass = BookStore.class;
        //获取构造器
        Constructor<BookStore> con = bookStoreClass.getConstructor();
        BookStore bookStore = con.newInstance();//实例化对象
        //获取Method
        Method method = bookStoreClass.getMethod("buy");
        //解析注解的步骤
        if(method.isAnnotationPresent(Book.class)){
            //获取Method对象上的Book注解
            Book bookAnno = method.getAnnotation(Book.class);
            //获取注解上的数据
            String bookName = bookAnno.value();
            double bookPrice = bookAnno.price();
            String[] bookAuthors = bookAnno.authors();
            System.out.println("书名:"+bookName);
            System.out.println("价格:"+bookPrice);
            System.out.println("作者:"+ Arrays.toString(bookAuthors));
        }
    }
}

小结

注解解析的步骤:

  1. 利用反射技术获取相关的对象:类、构造器、方法、变量
  2. 使用方法getAnnotation,获取自定义注解对象
  3. 使用注解对象,分别获取注解中的属性值

注解扩展小示例:

public class Student{
    private String name;//姓名
    private int age;//年龄
    private String gender;//性别
    private double score;//成绩
    private String id;//学号
}
数据:
    张三,20,男,90,it1001

利用注解+反射,给Student类中的成员变量赋值

//自定义注解
public @interface Entity{
    String value;
}
//Student类
public class Student{
    @Entity(value="张三")
    private String name;//姓名
    @Entiry(value="20")
    private int age;//年龄
    private String gender;//性别
    private double score;//成绩
    private String id;//学号
}

15_注解:综合案例


目标

  • 熟悉反射结合注解的使用 【会用】

路径

  1. 案例需求
  2. 案例分析
  1. 案例代码

需求

需求:模拟Junit测试的@Test

案例分析

  1. 模拟Junit测试的注释@Test,首先需要编写自定义注解@MyTest,并添加元注解,保证自定义注解只能修饰方法,且在运行时可以获得。
  2. 然后编写目标类(测试类),然后给目标方法(测试方法)使用 @MyTest注解,编写三个方法,其中两个加上@MyTest注解。
  1. 最后编写调用类,使用main方法调用目标类,模拟Junit的运行,只要有@MyTest注释的方法都会运行

案例代码

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 {
    //无属性注解
}
public class TestAnnotationParse {
    //方法1
    @MyTest
    public void method1(){
        System.out.println("我是方法1");
    }
    @MyTest
    public void method3(){
        System.out.println("我是方法3");
    }
    public void method2(){
        System.out.println("我是方法2");
    }
}
public class Test {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, InvocationTargetException {
        //获取Class对象
        Class<TestAnnotationParse> testAnnotationParseClass = TestAnnotationParse.class;
        //获取Class对象中,所有的Method方法
        Method[] methods = testAnnotationParseClass.getMethods();
        //遍历数组
        for (int i = 0; i < methods.length; i++) {
            //获取每一个Method对象
            Method method = methods[i];
            //判断Method对象上,是否存在@MyTest
            if(method.isAnnotationPresent(MyTest.class)){
                method.invoke(testAnnotationParseClass.newInstance());
            }
        }
    }
}

小结

注解解析的步骤:

  1. 获取Class对象 //类名.class、对象名.class、Class.forName(“…”)
  2. 基于Class对象,来获取:构造器/成员方法/成员变量 //getConstructor() getMethod() getField()
  3. 基于构造器/成员方法/成员变量,判断是否存在自定义注解 // isAnnotationPresent(注解.class)

存在:获取自定义注解对象 // 注解 对象 = 构造器/方法/变量/类 .getAnnotation(注解.class)

基于自定注解对象,获取其属性值 // 注解对象.属性()

16代理模式:动态代理_准备案例、提出问题


  • 需求:模拟某企业用户管理业务,需包含用户登录,用户删除,用户查询功能,并要统计每个功能的耗时
  • 分析:
  • 定义一个UserService表示用户业务接口,规定必须完成用户登录,用户删除,用户查询功能。
  • 定义一个实现类UserServiceImpl实现UserService,并完成相关功能,且统计每个功能的耗时。
  • 定义测试类,创建实现类对象,调用方法。
  • 代码实现:
package com.itheima.sh.web;
public interface UserService {
    void login();
    void delete();
    void query();
}
package com.itheima.sh.web;
public class UserServiceImpl implements UserService{
    @Override
    public void login() {
        try {
            long start = System.currentTimeMillis();
            System.out.println("登录");
            Thread.sleep(3000);
            long end = System.currentTimeMillis();
            System.out.println("耗时:"+(end-start));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void delete() {
        try {
            long start = System.currentTimeMillis();
            System.out.println("删除");
            Thread.sleep(4000);
            long end = System.currentTimeMillis();
            System.out.println("耗时:"+(end-start));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void query() {
        try {
            long start = System.currentTimeMillis();
            System.out.println("查询");
            Thread.sleep(5000);
            long end = System.currentTimeMillis();
            System.out.println("耗时:"+(end-start));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
package com.itheima.sh.web;
public class Test01 {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        userService.login();
        userService.delete();
        userService.query();
    }
}
  • 本案例存在哪些问题?

业务对象的的每个方法都要进行性能统计,存在大量重复的代码。

17代理模式:使用动态代理解决问题介绍


  • 概念
  • 代理就是被代理者没有能力或者不愿意去完成某件事情,需要找个人代替自己去完成这件事,动态代理就是用来对业务功能(方法)进行代理的。
  • 关键步骤
  • 1.必须有接口,实现类要实现接口(代理通常是基于接口实现的)。
  • 2.创建一个实现类的对象,该对象为业务对象,紧接着为业务对象做一个代理对象。
  • 相关API介绍

动态代理API

在java中实现动态代理,关键要使用到一个Proxy类和一个InvocationHandler接口

Proxy类

java.lang.reflect.Proxy:是 Java 动态代理机制的主类(父类),它提供了用于创建动态代理类和实例的静态方法

public static Object newProxyInstance(
                                      ClassLoader loader, 
                                      Class<?>[] interfaces, 
                                      InvocationHandler handle 
                                     ) 
**解释说明:    
- 返回值:     该方法返回就是动态生成的代理对象
- 参数列表说明:
  ClassLoader loader         :定义代理类的类加载器
  Class<?>[] interfaces      :代理类要实现的接口列表,要求与被代理类的接口一样
  InvocationHandler handle   :就是具体实现代理逻辑的接口 
//参数的应用:
ClassLoader loader     //对象.getClass().getClassLoader()  
           //目标对象通过getClass方法获取类的所有信息后,调用getClassLoader()方法来获取类加载器
           /*获取类加载器后,可以通过这个类型的加载器,在程序运行时,将生成的代理类加载到JVM即Java虚拟机中,以便运行时需要*/ 
Class<?>[] interfaces  //对象.getClass().getInterfaces() 
           //获取被代理类的所有接口信息,以便于生成的代理类可以具有代理类接口中的所有方法
InvocationHandler 
          //用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类方法的处理以及访问  

InvocationHandler接口

java.lang.reflect.InvocationHandler是代理对象的实际处理代理逻辑的接口,具体代理逻辑在其 invoke 方法中实现

public Object invoke(Object proxy, Method method, Object[] args)
**解释说明:
- 返回值:方法被代理后执行的结果
- 参数列表说明:
  Object proxy   :  就是代理对象(通常不使用)
  Method method  :  代理对象调用的方法
  Object[] args  :  被代理方法中的参数 (因为参数个数不定,所以用一个对象数组来表示)
                     如果方法不使用参数,则为 null
//所有代理对象调用的方法,执行是都会经过invoke
//因此如果要对某个方法进行代理增强,就可以在这个invoke方法中进行定义    

18代理模式:使用动态代理解决问题代码实现


package com.itheima.sh.web;
public interface UserService {
    void login();
    void delete();
    void query();
}
package com.itheima.sh.web;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Test02 {
    public static void main(String[] args) {
        ClassLoader loader = UserService.class.getClassLoader();
        Class[] interfaces = {UserService.class};
        InvocationHandler h = new InvocationHandler(){
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Exception{
                String name = method.getName();
                long start = System.currentTimeMillis();
                if("login".equals(name)){
                    //登录
                    System.out.println("登录");
                    Thread.sleep(3000);
                }else if("delete".equals(name)){
                    //删除
                    System.out.println("删除");
                    Thread.sleep(4000);
                }else if("query".equals(name)){
                    //查询
                    System.out.println("查询");
                    Thread.sleep(5000);
                }
                long end = System.currentTimeMillis();
                System.out.println(name+"耗时:"+(end-start));
                return null;
            }
        };
        UserService proxyUserServiceImpl = (UserService) Proxy.newProxyInstance(loader, interfaces, h);
        proxyUserServiceImpl.query();
        proxyUserServiceImpl.login();
        proxyUserServiceImpl.delete();
    }
}

19代理模式:使用动态代理解决问题代码实现


  • 非常的灵活,支持任意接口类型的实现类对象做代理,也可以直接为接口本身做代理。
  • 可以为被代理对象的所有方法做代理。
  • 可以在不改变方法源码的情况下,实现对方法功能的增强
  • 不仅简化了编程工作、提高了软件系统的可扩展性,同时也提高了开发效率。
相关文章
|
26天前
|
XML Java 编译器
Java学习十六—掌握注解:让编程更简单
Java 注解(Annotation)是一种特殊的语法结构,可以在代码中嵌入元数据。它们不直接影响代码的运行,但可以通过工具和框架提供额外的信息,帮助在编译、部署或运行时进行处理。
86 43
Java学习十六—掌握注解:让编程更简单
|
21天前
|
Java 开发者 Spring
[Java]自定义注解
本文介绍了Java中的四个元注解(@Target、@Retention、@Documented、@Inherited)及其使用方法,并详细讲解了自定义注解的定义和使用细节。文章还提到了Spring框架中的@AliasFor注解,通过示例帮助读者更好地理解和应用这些注解。文中强调了注解的生命周期、继承性和文档化特性,适合初学者和进阶开发者参考。
43 14
|
21天前
|
前端开发 Java
[Java]讲解@CallerSensitive注解
本文介绍了 `@CallerSensitive` 注解及其作用,通过 `Reflection.getCallerClass()` 方法返回调用方的 Class 对象。文章还详细解释了如何通过配置 VM Options 使自定义类被启动类加载器加载,以识别该注解。涉及的 VM Options 包括 `-Xbootclasspath`、`-Xbootclasspath/a` 和 `-Xbootclasspath/p`。最后,推荐了几篇关于 ClassLoader 的详细文章,供读者进一步学习。
29 12
|
23天前
|
设计模式 Java API
[Java]静态代理与动态代理(基于JDK1.8)
本文介绍了代理模式及其分类,包括静态代理和动态代理。静态代理分为面向接口和面向继承两种形式,分别通过手动创建代理类实现;动态代理则利用反射技术,在运行时动态创建代理对象,分为JDK动态代理和Cglib动态代理。文中通过具体代码示例详细讲解了各种代理模式的实现方式和应用场景。
18 0
[Java]静态代理与动态代理(基于JDK1.8)
|
23天前
|
存储 Java
[Java]反射
本文详细介绍了Java反射机制的基本概念、使用方法及其注意事项。首先解释了反射的定义和类加载过程,接着通过具体示例展示了如何使用反射获取和操作类的构造方法、方法和变量。文章还讨论了反射在类加载、内部类、父类成员访问等方面的特殊行为,并提供了通过反射跳过泛型检查的示例。最后,简要介绍了字面量和符号引用的概念。全文旨在帮助读者深入理解反射机制及其应用场景。
16 0
[Java]反射
|
1月前
|
安全 Java 测试技术
🌟Java零基础-反射:从入门到精通
【10月更文挑战第4天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
25 2
|
15天前
|
Java 编译器
Java进阶之标准注解
Java进阶之标准注解
28 0
|
26天前
|
Java
Java代码解释静态代理和动态代理的区别
### 静态代理与动态代理简介 **静态代理**:代理类在编译时已确定,目标对象和代理对象都实现同一接口。代理类包含对目标对象的引用,并在调用方法时添加额外操作。 **动态代理**:利用Java反射机制在运行时生成代理类,更加灵活。通过`Proxy`类和`InvocationHandler`接口实现,无需提前知道接口的具体实现细节。 示例代码展示了两种代理方式的实现,静态代理需要手动创建代理对象,而动态代理通过反射机制自动创建。
|
1月前
|
IDE Java 编译器
java的反射与注解
java的反射与注解
16 0
|
1月前
|
设计模式 缓存 Java
从源码学习Java动态代理|8月更文挑战
从源码学习Java动态代理|8月更文挑战