Java基础15-Java高级(单元测试、反射、注解、动态代理)

十五、Java高级

单元测试、反射、注解、动态代理。

1、单元测试

定义:就是针对最小的功能单元(方法),编写测试代码对其进行正确性测试。

1.1 Junit单元测试框架

可以用来对方 法进行测试,它是第三方公司开源出来的(很多开发工具已经集成了Junit框架,比如IDEA)

优点:可以灵活的编写测试代码,可以针对某个方法执行测试,也支持一键 完成对全部方法的自动化测试,且各自独立。不需要程序员去分析测试的结果,会自动生成测试报告出来。

1.2 测试案例

某个系统,有多个业务方法,请使用Junit单元测试框架, 编写测试代码,完成对这些方法的正确性测试。

具体测试步骤:

  1. 将Junit框架的jar包导 入到项目中(注意: IDEA集成了Junit框架,不需要我们自己手工导入了)
  2. 为需要测试的业务类,定义对应的测试类,并为每个业务方法,编写对应的测试方法(必须:公共、无参、无返回值)
  3. 测试方法 上必须声明@Test注解,然后在测试方法中,编写代码调用被测试的业务方法进行测试。
  4. 开始测试: 选中测试方法,右键选择"JUnit运行",如果测试通过则是绿色;如果测试失败,则是红色。

1、只测试某个方法:直接点击该方法的左侧运行按钮运行即可

2、测试该测试类的所以方法:点击该参数类的左侧运行按钮运行即可

3、要测试该项目的所以测试类:直接右击该项目名------>点击 run All Tests

java 复制代码
//工具类
public class Function {
    //获取字符串长度
    public static int getStringLenght(String str){
         if(str==null){
             return 0;
         }
       return str.length();
    }

    //获取字符串最后一个字母的索引
    public static int  getStringMaxIndex(String  str){
        if(str==null){
            return -1;
        }
        return str.length();
    }
}
java 复制代码
//工具类的测试类
//点击在测试类左侧的运行按钮就测试所以的方法
public class FunctionTest {

    @Test  //测试类(点击左侧的运行按钮即可运行所对应的方法)
    //保证方法是(public、无返回值、无形参)
    public void getStringLenghtTest(){
        //直接调用要测试的方法(这里写的是静态方法,直接通过类名调取)
        int len= Function.getStringLenght("hello");
        int len2=Function.getStringLenght(null);
        System.out.println(len);
        System.out.println(len2);
    }

    @Test
    public void getStringMaxIndexTest(){
        int index1=Function.getStringMaxIndex("hello");
        int index2=Function.getStringMaxIndex(null);
        System.out.println(index1);
        System.out.println(index2);  //会发现测试没有报错,但是结果可能有问题。

        //可以使用结果断言,就是可以用自己的预测结果和方法得出的结果进行比较,看看是不是一样的。
        //参数(有误时的提示信息,自己预测结果,方法得出的结果)
        Assert.assertEquals("测试结果有误:",4,index1);
    }
}
Junit单元测试常见注解 说明
@Test 测试类中的方法必须用它修饰才能成为测试方法,才能启动执行
@Before Junit5改名为 ( @BeforeEach) 用来修饰一个实例方法,该方法会在每一个测试方法执行之前执行一次。
@After Junit5改名为 (@BeforeEach) 用来修饰一个实例方法,该方法会在每一个测试方法执行之后执行一次。
@BeforeClass Junit5改名为(@BeforeAll ) 用来修饰一个静态方法,该方法会在所有测试方法之前只执行一次。
@AfterClass Junit5改名为(@AfterAll) 用来修饰一个静态方法,该方法会在所有测试方法之后只执行一次。

在测试方法执行前执行的方法,常用于:初始化资源。

在测试方法执行完后再执行的方法,常用于:释放资源。

2、反射

反射就是:加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)。

作用:反射主要是用来做框架的

学习获取类的信息、操作它们,实现步骤:

  1. 反射第一步:加载类,获取类的字节码: Class对象
  2. 获取类的构造器:Constructor对象
  3. 获取类的成员变量:Field对象
  4. 获取类的成员方法::Method对象
2.1 反射第一步:加载类,获取类的字节码: Class对象

获取Class对象的三种方式:

  1. Class c1 =类名.class
  2. 调用Class提供方 法: public static Class forName(String package);
  3. Object提供的方法: public Class getClass(); Class c3 =对象.getClass();
java 复制代码
public class Student {
    private String name;
    private String sex;
    private  int  age;
}
java 复制代码
//测试类
public class ReflectTest {
    public static void main(String[] args) throws Exception {
        //Class  c1 =类名.class
        Class c1=Student.class;
        System.out.println(c1.getName());  //获取全类类名(包名加类名)
        System.out.println(c1.getSimpleName()); //获取简单类名(类名)

        //调用Class提供方 法: public static Class forName(String package);
        Class c2=Class.forName("akc4.reflect.Student");  //参数为全类类名
        System.out.println(c1==c2);  //等到的都是同一个类(true)

        //Object提供的方法: public Class getClass(); Class c3 =对象.getClass();
        Student  student=new Student();
        Class c3=student.getClass();
        System.out.println(c2==c3);  //等到的都是同一个类(true)

    }
}
2.2 获取类的构造器:Constructor对象
Class提供了从类中获取构造器的方法 说明
Constructor<?> [ ] getConstructors() 获取全部构造器(只能获取public修饰的)
Constructor<?> [ ] getDeclaredConstructors() 获取全部构造器(只要存在就能拿到)
Constructor getConstructor(Class<?> ... parmeterTypes ) 获取某个构造器(只能获取public修饰的)
Constructor getDeclaredConstructor( Class<?> ... paramerTyoes ) 获取某个构造器(只要存在就能拿到)
java 复制代码
//学生实体类
public class Student {
    private String name;
    private String sex;
    private  int  age;


    public Student() {
    }

    private Student(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }

    public Student(String name, String sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
}
java 复制代码
//测试类
public class StudentTest {

    @After  //每个测试方法结束后都会执行
    public void soutAfter(){
        System.out.println("---------------");
    }

    //获取多少构造器
    @Test
    public void testGetConstructors(){
        //1、获取到对应类的类Class对象
        Class  c1=Student.class;
        //2、通过 getConstructors()方法获取到所有用public修饰的构造器
        Constructor[] cons1=c1.getConstructors();
        for (Constructor constructor : cons1) {
            //获取构造器名和形参个数
            System.out.println(constructor.getName()+"--->"+constructor.getParameterCount());
        }

        System.out.println("============");
        //3、通过getDeclaredConstructors() 方法获取所有的构造器(一般用这个获取多个构造器)
        Constructor[] cons2=c1.getDeclaredConstructors();
        for (Constructor constructor : cons2) {
            //获取构造器名和形参个数
            System.out.println(constructor.getName()+"--->"+constructor.getParameterCount());
        }
    }

    @Test
    public void testGetDeclaredConstructor() throws Exception {
        //1、获取对应类的Class
        Class c2=Student.class;
        //2、通过getConstructor(形参类型)方法获取public修饰的某个构造器
        Constructor con1=c2.getConstructor(); //获取无参构造器(public修饰的)
        //获取public修饰的形参为三个,且形参类型对应的构造器
        Constructor  cons2=c2.getConstructor(String.class,String.class,int.class);
        //获取指定的任何一个构造器,不限修饰类型
        Constructor  cons3=c2.getDeclaredConstructor(String.class,String.class);
        System.out.println(con1.getName()+" "+cons2.getName()+" "+cons3.getName());

    }

}

获取类构造器的作用:依然是初始化对象返回

Constructor对象提供的方法 说明
T newIntstance(Object...initargs) 调用此构造器对象表示的构造器,并传入参数,完成对象的初始化并返回
public void setAccessible( boolean flag ) 设置为true,表示禁止检查访问控制,就是即使是私有的构造器也能访问(暴力反射)
java 复制代码
//学生实体类
public class Student {
    private String name;
    private String sex;
    private  int  age;


    public Student() {
        System.out.println("无参构造器被调用了");
    }



    private Student(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }

    public Student(String name, String sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                '}';
    }
}
java 复制代码
//测试类
public class StudentTest {
 @Test
    public void testGetDeclaredConstructor() throws Exception {
        //1、获取对应类的Class
        Class c2=Student.class;
        //2、通过getConstructor(形参类型)方法获取public修饰的某个构造器
        Constructor con1=c2.getConstructor(); //获取无参构造器(public修饰的)
        //通过调用无参构造器的newInstance方法来初始对象,并返回
        Student student=(Student) con1.newInstance();  
        System.out.println(student);


        //获取一个参数为2个的,且参数类型对应的任意一个构造器
        Constructor  cons3=c2.getDeclaredConstructor(String.class,String.class);
        cons3.setAccessible(true); //暴力反射, 即使是private修饰的也能调用了                          
         Student student1=(Student) cons3.newInstance("小明","男");
        System.out.println(student1);

    }

}
2.3 获取类的成员变量:Field对象

Class提供了从类中获取成员变量的方法

方法 说明
public Field[ ] getFields() 获取类id全部成员变量(只能获取public修饰的)
public Field[ ] getDeclaredFields() 获取类的全部成员变量(只要存在就能拿到)
public Field getField(Sting name) 获取类的某个成员变量(只能获取public修饰的)
public Field getDeclaredField(String name) 获取类的某个成员变量(只要存在就能拿到)

获取到成员变量的作用:依然是赋值、取值。

方法 说明
void set(Object obj , Object value) 赋值
Object get( Object obj ) 取值
public void setAccessible( boolean flag ) 设置true ,表示禁止检查访问控制(暴力反射)
java 复制代码
//实体类
public class Student {
    public  String name;
    public   String  id;
    private String sex;
    private  int  age;
        public Student() {
    }
}
java 复制代码
//测试类
public class StudentTest {

    @After  //每个测试方法结束后都会执行
    public void soutAfter(){
        System.out.println("---------------");
    } 
@Test
    public  void  testFields(){
        //1、获取到对应类的Class对象
        Class c=Student.class;
        //2、获取到所有用public修饰的成员变量
        Field[] fields=c.getFields();
        //3、遍历拿到的成员变量
        for (Field field : fields) {
            //输出变量名和变量类型
            System.out.println(field.getName()+"==>"+field.getType());
        }

        System.out.println("==========");
        //2、获取全部成员变量
        Field[] fields1=c.getDeclaredFields();
        //3、遍历拿到的成员变量
        for (Field field : fields1) {
            //输出变量名和变量类型
            System.out.println(field.getName()+"==>"+field.getType());
        }
    }

       @Test
    public  void  testField() throws Exception {
        //1、获取到对应类的Class对象
         Class  c1=Student.class;
         //2、获取public修饰的某个成员变量(成员变量名)
        Field field= c1.getField("name");
        System.out.println(field.getName()+"==>"+field.getType());

        System.out.println("============");
        //2、获取某个成员变量。不限修饰(成员变量名)
        Field field1=c1.getDeclaredField("age");
        System.out.println(field1.getName()+"==>"+field1.getType());

        //3、为成员变量赋值
        //3.1 创建一个对象
           Student student=new Student();
           //由于field1对应的age是私有的成员变量,所以要暴力反向
          field1.setAccessible(true);
          //赋值(要赋值的具体对象,符的值)
          field1.set(student,20);

          //获取值
         int  age=(int)field1.get(student);
        System.out.println(age);
    }
}
2.4 获取类的成员方法::Method对象

Class提供了从类中获取成员方法的API。

方法 说明
Method[ ] getMethods() 获取类的全部成员方法(只能获取public修饰的)
Method[ ] getDeclaredMethods() 获取类的全部成员方法(只要存在就能拿到)
Method getMethod(String name, Class<?> ... parameterTypes) 获取类的某个成员方法(只能获取public修饰的)参数:(方法名,参数类型,如:String.class)
Method getDeclaredMethod(String name , Class<?> ... parameterType ) 获取类的某个成员方法(只要存在就能拿到)参数:(方法名,参数类型,如:String.class)

成员方法的作用:依然是执行

Method提供的方法 说明
public Object invoke( Object obj , Object ... args ) 触发某个对象的该方法执行
public void setAccessible( boolean flag ) 设置true,表示禁止检查访问控制(暴力反射)
java 复制代码
//实体类
public class Student {
    private String name;
    private String sex;
    private  int  age;

    public Student() {
    }

   private  String run(int num){
        return "跑"+num+"圈操场!";
   }
}
java 复制代码
//测试类 
public class StudentTest {
   @Test
    public void testMethod() throws Exception {
        //1、创建一个类,对应的Class
        Class  c=Student.class;
        //获取某个方法,不限修饰,参数为:要获取方法的方法名,形参列表的各个类型
       Method method= c.getDeclaredMethod("run",int.class);
        //2、由于run方法是私有的所以要暴力反向
        method.setAccessible(true);

        //3、获取某个方法,需要一个对应对象
        Student student=new Student();

        //4、调用该方法,并传入参数(要调用对象的对象名,调用方法的参数)
        String  str=  (String) method.invoke(student,10);
        System.out.println(str);

    }

}
2.5 反射的运用场景

基本作用:可以得到一个类的全部成分然后操作。可以破坏封装性。

最重要的用途是:适合做Java的框架,基本上,主流的框架都会基于反射设计出一些通用的功能。

使用反射做一个简易版的框架

需求:对于任意一个对象,该框架都可以把对象的字段名和对应的值,保存到文件中去。

实现步骤:

①定义一个方法,可以接收任意对象。

②每收到一个对象后,使用反射获取该对象的Class对象,然后获取全部的成员变量。

③遍历成员变量,然后提取成员变量在该对象中的具体值。

④把成员变量名、和其值,写出到文件中去即可。

3、注解( Annotation )

就是Java代码里的特殊标记,比如: @Override、 @Test等,作用是:让其他程序根据注解信息来决定怎么执行该程序。

注意:注解可以用在类上、构造器上、方法上、成员变量上、参数上、等位置处。

3.1 自定义注解
java 复制代码
//自定义注解格式
public   @interface  注解名称{
    public  属性类型  属性名()  default  默认值;
}
java 复制代码
//注解
public @interface MyTest {
    //默认public可以不写
      public String  name();
      //可以写默认值(写了,在赋值的时候可以不写)
      int  age() default 10;
      String[] hobby();
}
java 复制代码
//测试注解
@MyTest(name="小明",age=19,hobby={"唱","跳","篮球"})
public class AnnotationTest {
    public static void main(String[] args) {

    }
    @MyTest(name="小红",hobby={"唱","跳","篮球"})
    public static void run(){}
}

1、特殊属性名: value

如果注解中只有一个value属性,使用注解时, value名称可以不写!

2、注解的本质

注解本质是一个接口,Java中所有注解都是继承了Annotation接口的。

@注解(...):其实就是一个实现类对象,实现了该注解以及Annotation接口。

3.2 元注解

是指的是修饰注解的注解

常用的2个元注解:@Target@Retention

java 复制代码
@Retention( Retent ionPol icy . RUNTIME )   //元注解1
@Target({ElementType .METHOD})             //元注解2
public @interface Test {
}
3.2.1 @Target 元注解

作用:声明被修饰的注解只能在哪些位置使用。

java 复制代码
//格式
@Target(ElementType.TYPE)
public @interface Test {  }
  1. TYPE:类、接口;
  2. FIELD:成员变量;
  3. METHOD:成员方法
  4. PARAMETER:方法参数;
  5. CONSTRUCTOR:构造器;
  6. LOCAL_VARIABLE:局部变量;
java 复制代码
//限定修饰类型为成员变量
@Target(ElementType.FIELD)
public @interface MyTest {
     String  value();
}
java 复制代码
public class AnnotationTest {
    //现在只能修饰成员变量了
   @MyTest("hello")
  private String name;
}
3.2.2 Retention 元注解

作用:声明注解的保留周期。

java 复制代码
//格式
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {  }
  1. SOURCE:只作用在源码阶段,字节码文件中不存在。
  2. CLASS(默认值):保留到字节码文件阶段,运行阶段不存在。
  3. RUNTIME(开发常用):一直保留到运行阶段。
java 复制代码
//一直保留到运行阶段
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
     String  value();
}
java 复制代码
public class AnnotationTest {
    //现在只能修饰成员变量了
   @MyTest("hello")
  private String name;
}
3.2.2 注解的解析

定义:就是判断类上、方法上、成员变量上是否存在注解,并把注解里的内容给解析出来。
指导思想:要解析谁上面的注解,就应该先拿到谁。比如要解析类上面的注解,则应该先获取该类的Class对象,再通过Class对象解析其上面的注解。比如要解析成员方法上的注解,则应该获取到该成员方法的Method对象,再通过Method对象解析其上面的注解。
Class、Method 、Field , Constructor.都实现了AnnotatedElement接口,它们都拥有解析注解的能力。

AnnotatedElement接口提供的解析注解方法 说明
public Anotation[ ] getDeclaredAnnotations() 获取当前对象上面的注解
public T getDeclaredAnnotation(Class annottationClass) 获取指定的注解对象
public boolean isAnnotationPresent(Class annotationClass) 判断当前对象上是否存在某个注解

解析注解案例:

①定义注解MyTest4, 要求如:

➢包含属性: String value()

➢包含属性: double aaa(),默认值为100

➢包含属性: String[] bbb()

➢限制注解使用的位置: 类和成员方法上

➢指定注解的有效范围: - -直到运行时

②定义一个类叫: Demo,在类中定义一个test1方法, 并在该类和其方法.上使用MyTest4注解

③定义AnnotationTest3测试类 ,解析Demo类中的全部注解。

java 复制代码
//自定义注解
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
    String  value();
    double  aaa() default 100;
    String[]  bbb();
}
java 复制代码
//使用注解的类
@MyTest(value = "java",aaa=120,bbb = {"python","HTML"})
public class Demo {
    @MyTest(value = "JS",bbb = {"C语言","C++"})
    public void test1(){}
}
java 复制代码
//测试类
public class AnnotationTest {
    @Test
    public void testClassAnnotation(){
        //1、获取到对应类的对象
        Class c=Demo.class;
        //2、解析类上的注解
        // 判断类对象是否有对应的注解
        if (c.isAnnotationPresent(MyTest.class)){
            //3、获取到类上的注解对象
            MyTest myTest=(MyTest) c.getDeclaredAnnotation(MyTest.class);
            //4、通过类上的对象获取到对应的参数
            System.out.println(myTest.value());
            System.out.println(myTest.aaa());
            System.out.println(Arrays.toString(myTest.bbb()));
        }
    }


    @Test
    public void testMethodAnnotation() throws Exception {
        //1、获取到对应的类对象
        Class c=Demo.class;
        //2、获取到类的Method对象
        Method m=c.getDeclaredMethod("test1");
        //3、判断方法上是否有对应的注解
        if(m.isAnnotationPresent(MyTest.class)){
            //4、获取到注解的对象
            MyTest myTest=(MyTest)m.getDeclaredAnnotation(MyTest.class);
            //5、通过注解对象获取获取到方法上注解的参数
            System.out.println(myTest.value());
            System.out.println(myTest.aaa());
            System.out.println(Arrays.toString(myTest.bbb()));
        }
    }
}
3.2.3 注解的运用场景

需求:定义若干个方法,只要加了MyTest注解,就会触发该方法执行。

分析:

①定义一个自定义注解MyTest,只能注解方法,存活范围是一直都在。

②定义若干个方法,部分方法加.上@MyTest注解修饰,部分方法不加。

③模拟一个junit程序,可以触发加了@MyTest注解的方法执行。

java 复制代码
//注解
@Target(ElementType.METHOD)        //只能方法才能使用的注解
@Retention(RetentionPolicy.RUNTIME)   //触发范围:一直到运行阶段
public @interface MyTest {
}
java 复制代码
public class Demo {
    //定义一下方法,要求只有加了注解的方法才能触发

    @MyTest()
    public void test1(){
        System.out.println("=======test1=======");
    }

    @MyTest
    public void test2(){
        System.out.println("=======test2=======");
    }

    public void test3(){
        System.out.println("=======test3=======");
    }

    @MyTest
    public void test4(){
        System.out.println("=======test4=======");
    }

    public static void main(String[] args) throws Exception{
        //1、获取到类这个Class对象
       Class c= Demo.class;

       //2、通过类对象获取到类对象里面的所有方法
        Method[] methods= c.getDeclaredMethods();
        //3、通过遍历获取到里面的每一个方法
        for (Method method : methods) {
            //4、判断里面的每一个方法是否带有注解
            if(method.isAnnotationPresent(MyTest.class)){
                //5、创建一个要被执行方法的对象,将这个对象作为参数
                Demo demo=new Demo();
                //执行带有注解的这个方法
                method.invoke(demo);
            }
        }
    }

}

4、动态代理

代理是一种设计模式,它提供了一种机制,通过代理对象来访问目标对象,从而在不修改原始对象的基础上添加额外的功能或限制访问。
java.lang.reflect.Proxy类:提供了为对象产生代理对象的方法:

java 复制代码
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
    /*
参数一:用于指定用哪个类加载器,去加载生成的代理类
参数二:指定接口,这些接口用于指定生成的代理长什么,也就是有哪些方法
参数三:用来指定生成的代理对象要干什么事情
    */

案例:蔡徐坤他有很多的才艺(唱歌,跳舞,打篮球...),但是呢,他肯定不会白白的在大众面向做这些,肯定是要收钱的,而且还要准备舞台什么的;他又不会去自己去收钱、搭建舞蹈什么的,因为他只负责唱、跳等,自己擅长的领域,这时其它的工作就会交给代理去做,代理做好前期工作后,代理才叫他来展示他的才艺。下面是实现代码:

java 复制代码
//大明星的才艺接口
public interface Star {
    String sing(String singname);
    void  dance();
    void basketball();
}
java 复制代码
//大明星类
//大明星要学习这些才艺(实现接口的方法)
public class BigStar implements Star {
    private  String name;

    public BigStar(String name) {
        this.name = name;
    }

    //创建2个方法
    public String sing(String singName){
        System.out.println(this.name+" 唱完了 "+singName);
        return "唱得怎么样?谢谢!谢谢!";
    }

    public void  dance(){
        System.out.println(this.name+" 跳了");
    }

    public void basketball(){
        System.out.println(this.name+" 打篮球了");
    }
}
java 复制代码
//一个代理工具类(大明星可以在这里找代理)
public class ProxyUtil {
    //1、创建一个静态方法,用来完成代理工作,接收一个大明星类(就是为bigStar做代理)
    public static  Star  createProxy(BigStar bigStar){

        //2、创建一个代理对象
        /*Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
          参数1:用于指定一个类加载器(一般就行写这个类的类加载器)
          参数2:指定生成的代理长什么样子,也就是有哪些方法(是一个数组装其来的),由于这里只接收一个方法,就把它直接放到数组里去
          参数3:用于指定生成的代理要做什么事情,它是一个接口,所以要不能直接创建对象,就new一个匿名内部类对象来指定代理对象做什么事情
          */

         Star starProxy=(Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), new Class[]{Star.class}, new InvocationHandler() {
            //invoke方法:等一下会去main方法调用这个工具类,将bigStar对象作为参数,得到一个Star对象,再通过Star对象调用sing和dance方法,调用这两个方法就会去调用invoke方法。
            //sing和dance方法被调用时,也会把3个参数填到invoke方法中
            //参数1:java会把当前的代理对象当作一个Object对象放到其中
            //参数2:java会把,调用的方法当作Method传进来,如果外面在调用sing方法,那么method就是sing方法
            //参数3:被调用方法的参数,java会把被调用的方法的产生传到args数组中
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    //代理对象要做的事情,会在这里写代码
                     //1、通过method来判断,被调用的是哪个方法
                if(method.getName().equals("sing")){
                    System.out.println("准备话筒,收100块!");
                    //2、执行被代理发方法(参数为:被代理的对象,被调用方法的参数),有返回值的直接返回
                   return method.invoke(bigStar,args);
                }else if(method.getName().equals("dance")){
                    System.out.println("准备一个舞台!收20块!");
                    //2、执行被代理发方法(参数为:被代理的对象,被调用方法的参数)
                   return method.invoke(bigStar,args);
                }else {
                    //其它方法
                  return   method.invoke(bigStar,args);
                }
            }
        });
         //将代理对象返回出去
        return starProxy;
    }
}
java 复制代码
//测试类(大明星展示才艺类)
public class Test {
    public static void main(String[] args) {
        //通过有参构造器创建一个需要被代理的对象(创建了蔡徐坤大明星)
        BigStar bigStar=new BigStar("蔡徐坤");
        //调用代理工具类静态方法,创建一个代理对象,将需要被代理的对象传过去(蔡徐坤找来一个代理)
        Star star=ProxyUtil.createProxy(bigStar);
        //通过代理对象,调用代理方法
        String str = star.sing("鸡你太美");
        System.out.println(str);
       //通过代理对象,调用代理方法
         star.dance();            
        //通过代理对象,调用代理方法
        star.basketball(); 

    }
}
相关推荐
啾啾Fun5 分钟前
Java反射操作百倍性能优化
java·性能优化·反射·缓存思想
20岁30年经验的码农12 分钟前
若依微服务Openfeign接口调用超时问题
java·微服务·架构
曲莫终20 分钟前
SpEl表达式之强大的集合选择(Collection Selection)和集合投影(Collection Projection)
java·spring boot·spring
ajassi200038 分钟前
开源 java android app 开发(十二)封库.aar
android·java·linux·开源
q5673152344 分钟前
Java使用Selenium反爬虫优化方案
java·开发语言·分布式·爬虫·selenium
kaikaile19951 小时前
解密Spring Boot:深入理解条件装配与条件注解
java·spring boot·spring
守护者1701 小时前
JAVA学习-练习试用Java实现“一个词频统计工具 :读取文本文件,统计并输出每个单词的频率”
java·学习
bing_1581 小时前
Spring Boot 中ConditionalOnClass、ConditionalOnMissingBean 注解详解
java·spring boot·后端
ergdfhgerty1 小时前
斐讯N1部署Armbian与CasaOS实现远程存储管理
java·docker
勤奋的知更鸟1 小时前
Java性能测试工具列举
java·开发语言·测试工具