JAVA进阶--Junit单元测试、反射--2022年9月19日

第一节   Junit单元测试

  1、Junit单元测试是做什么的

    测试类中方法的正确性的

  2、Junit单元测试的有点是什么

    Junit可以选择执行哪些测试方法,可以一键执行全部测试方法的测试

    Junit可以生测试报告,如果测试良好则是绿色;如果测试失败,则是红色

    单元测试中的某个方法测试失败了,不会影响其他测试方法的测试

  

  ====================================================================================================

  

 

  3、Junit单元测试的实现过程是什么样的

    必须导入Junit框架的jar包

    定义的测试方法必须是无参数返回值,且公开的方法

    测试方法使用@Test注解标记

    

  4、Junit测试某个方法,测试全部方法怎么处理?成功的标志是什么

    测试某个方法直接右键该方法启动测试

    测试全部方法,可以选择类或者模块启动

    红色失败,绿色通过,黄色表示方法没问题,但是预期结果不一样

 1 package com.itheima.d1_junit;
 2 
 3 /**
 4    业务方法
 5  */
 6 public class UserService {
 7     public String loginName(String loginName , String passWord){
 8         if("admin".equals(loginName) && "123456".equals(passWord)){
 9             return "登录成功";
10         }else {
11             return "用户名或者密码有问题";
12         }
13     }
14 
15     public void selectNames(){
16         System.out.println(10/2);
17         System.out.println("查询全部用户名称成功~~");
18     }
19 }
UserService
 1 package com.itheima.d1_junit;
 2 
 3 import org.junit.*;
 4 
 5 /**
 6    测试类
 7  */
 8 public class TestUserService {
 9 
10     // 修饰实例方法的
11     @Before
12     public void before(){
13         System.out.println("===before方法执行一次===");
14     }
15 
16     @After
17     public void after(){
18         System.out.println("===after方法执行一次===");
19     }
20 
21     // 修饰静态方法
22     @BeforeClass
23     public static void beforeClass(){
24         System.out.println("===beforeClass方法执行一次===");
25     }
26 
27     @AfterClass
28     public static void afterClass(){
29         System.out.println("===afterClass方法执行一次===");
30     }
31 
32 
33     /**
34        测试方法
35        注意点:
36             1、必须是公开的,无参数 无返回值的方法
37             2、测试方法必须使用@Test注解标记。
38      */
39     @Test
40     public void testLoginName(){
41         UserService userService = new UserService();
42         String rs = userService.loginName("admin","123456");
43 
44         // 进行预期结果的正确性测试:断言。
45         Assert.assertEquals("您的登录业务可能出现问题", "登录成功", rs );
46     }
47 
48     @Test
49     public void testSelectNames(){
50         UserService userService = new UserService();
51         userService.selectNames();
52     }
53 
54 }
TestUserService  

  5、单元测试常用注解

    

 

 

     

 1 package com.itheima.d1_junit;
 2 
 3 import org.junit.*;
 4 
 5 /**
 6    测试类
 7  */
 8 public class TestUserService {
 9 
10     // 修饰实例方法的
11     @Before
12     public void before(){
13         System.out.println("===before方法执行一次===");
14     }
15 
16     @After
17     public void after(){
18         System.out.println("===after方法执行一次===");
19     }
20 
21     // 修饰静态方法
22     @BeforeClass
23     public static void beforeClass(){
24         System.out.println("===beforeClass方法执行一次===");
25     }
26 
27     @AfterClass
28     public static void afterClass(){
29         System.out.println("===afterClass方法执行一次===");
30     }
31 
32 
33     /**
34        测试方法
35        注意点:
36             1、必须是公开的,无参数 无返回值的方法
37             2、测试方法必须使用@Test注解标记。
38      */
39     @Test
40     public void testLoginName(){
41         UserService userService = new UserService();
42         String rs = userService.loginName("admin","123456");
43 
44         // 进行预期结果的正确性测试:断言。
45         Assert.assertEquals("您的登录业务可能出现问题", "登录成功", rs );
46     }
47 
48     @Test
49     public void testSelectNames(){
50         UserService userService = new UserService();
51         userService.selectNames();
52     }
53 
54 }
View Code

第二节   反射

  1、反射的基本作用、关键?

    反射是在运行时获取类的字节码文件对象:然后可以解析类中的全部成分

    反射的核心思想和关键就是:得到编译以后的class文件对象

    

  2、反射的第一步是什么

    获取Class类对象,如此才可以解析类的全部成分

  3、获取Class类的对象的三种方式

    方式一:Class c1 = Class.forName("全类名");

    方式二:Class c2 = 类名.class;

    方式三:Class c3 = 对象.getClass();

    

1 package com.itmao.d2_reflect_class;
2 
3 public class Student {
4 }
Student
 1 package com.itmao.d2_reflect_class;
 2 
 3 /**
 4    目标:反射的第一步:获取Class对象
 5  */
 6 public class Test {
 7     public static void main(String[] args) throws Exception {
 8         // 1、Class类中的一个静态方法:forName(全限名:包名 + 类名)
 9 
10 
11         // 2、类名.class
12         Class c1 = Student.class;
13         System.out.println(c1);
14 
15         // 3、对象.getClass() 获取对象对应类的Class对象。
16 
17     }
18 }
View Code

  4、利用反射技术获取构造器对象的方式

    getDeclaredConstructors()

    getDeclaredConstructor(Class<?>...parameterTypes)

    

  5、反射得到的构造器可以做什么

    依然是创建对象的

      public newInstance(Object...initargs)

    如果是非public的构造器,需要打开权限(暴力反射),然后再创建对象

      setAccessible(boolean)

      反射可以破坏封装性,私有的也可以执行了

    

 1 package com.itheima.d3_reflect_constructor;
 2 
 3 public class Student {
 4     private String name;
 5     private int age;
 6 
 7     private Student(){
 8         System.out.println("无参数构造器执行!");
 9     }
10 
11     public Student(String name, int age) {
12         System.out.println("有参数构造器执行!");
13         this.name = name;
14         this.age = age;
15     }
16 
17     public String getName() {
18         return name;
19     }
20 
21     public void setName(String name) {
22         this.name = name;
23     }
24 
25     public int getAge() {
26         return age;
27     }
28 
29     public void setAge(int age) {
30         this.age = age;
31     }
32 
33     @Override
34     public String toString() {
35         return "Student{" +
36                 "name='" + name + '\'' +
37                 ", age=" + age +
38                 '}';
39     }
40 }
Student
 1 package com.itheima.d3_reflect_constructor;
 2 
 3 
 4 import org.junit.Test;
 5 
 6 import java.lang.reflect.Constructor;
 7 
 8 /**
 9     目标:反射_获取Constructor构造器对象.
10 
11     反射的第一步是先得到Class类对象。(Class文件)
12 
13     反射中Class类型获取构造器提供了很多的API:
14          1. Constructor getConstructor(Class... parameterTypes)
15             根据参数匹配获取某个构造器,只能拿public修饰的构造器,几乎不用!
16          2. Constructor getDeclaredConstructor(Class... parameterTypes)
17             根据参数匹配获取某个构造器,只要申明就可以定位,不关心权限修饰符,建议使用!
18          3. Constructor[] getConstructors()
19             获取所有的构造器,只能拿public修饰的构造器。几乎不用!!太弱了!
20          4. Constructor[] getDeclaredConstructors()
21             获取所有申明的构造器,只要你写我就能拿到,无所谓权限。建议使用!!
22     小结:
23         获取类的全部构造器对象: Constructor[] getDeclaredConstructors()
24             -- 获取所有申明的构造器,只要你写我就能拿到,无所谓权限。建议使用!!
25         获取类的某个构造器对象:Constructor getDeclaredConstructor(Class... parameterTypes)
26             -- 根据参数匹配获取某个构造器,只要申明就可以定位,不关心权限修饰符,建议使用!
27 
28  */
29 public class TestStudent01 {
30     // 1. getConstructors:
31     // 获取全部的构造器:只能获取public修饰的构造器。
32     // Constructor[] getConstructors()
33     @Test
34     public void getConstructors(){
35         // a.第一步:获取类对象
36         Class c = Student.class;
37         // b.提取类中的全部的构造器对象(这里只能拿public修饰)
38         Constructor[] constructors = c.getConstructors();
39         // c.遍历构造器
40         for (Constructor constructor : constructors) {
41             System.out.println(constructor.getName() + "===>" + constructor.getParameterCount());
42         }
43     }
44 
45 
46     // 2.getDeclaredConstructors():
47     // 获取全部的构造器:只要你敢写,这里就能拿到,无所谓权限是否可及。
48     @Test
49     public void getDeclaredConstructors(){
50         // a.第一步:获取类对象
51         Class c = Student.class;
52         // b.提取类中的全部的构造器对象
53         Constructor[] constructors = c.getDeclaredConstructors();
54         // c.遍历构造器
55         for (Constructor constructor : constructors) {
56             System.out.println(constructor.getName() + "===>" + constructor.getParameterCount());
57         }
58     }
59 
60     // 3.getConstructor(Class... parameterTypes)
61     // 获取某个构造器:只能拿public修饰的某个构造器
62     @Test
63     public void getConstructor() throws Exception {
64         // a.第一步:获取类对象
65         Class c = Student.class;
66         // b.定位单个构造器对象 (按照参数定位无参数构造器 只能拿public修饰的某个构造器)
67         Constructor cons = c.getConstructor();
68         System.out.println(cons.getName() + "===>" + cons.getParameterCount());
69     }
70 
71 
72     // 4.getConstructor(Class... parameterTypes)
73     // 获取某个构造器:只要你敢写,这里就能拿到,无所谓权限是否可及。
74     @Test
75     public void getDeclaredConstructor() throws Exception {
76         // a.第一步:获取类对象
77         Class c = Student.class;
78         // b.定位单个构造器对象 (按照参数定位无参数构造器)
79         Constructor cons = c.getDeclaredConstructor();
80         System.out.println(cons.getName() + "===>" + cons.getParameterCount());
81 
82         // c.定位某个有参构造器
83         Constructor cons1 = c.getDeclaredConstructor(String.class, int.class);
84         System.out.println(cons1.getName() + "===>" + cons1.getParameterCount());
85 
86     }
87 
88 }
TestStudentDemo1
 1 package com.itheima.d3_reflect_constructor;
 2 
 3 import org.junit.Test;
 4 
 5 import java.lang.reflect.Constructor;
 6 
 7 /**
 8     目标: 反射_获取Constructor构造器然后通过这个构造器初始化对象。
 9 
10     反射获取Class中的构造器对象Constructor作用:
11             也是初始化并得到类的一个对象返回。
12 
13     Constructor的API:
14          1. T newInstance(Object... initargs)
15                 创建对象,注入构造器需要的数据。
16          2. void setAccessible(true)
17                 修改访问权限,true代表暴力攻破权限,false表示保留不可访问权限(暴力反射)
18     小结:
19         可以通过定位类的构造器对象。
20         如果构造器对象没有访问权限可以通过:void setAccessible(true)打开权限
21         构造器可以通过T newInstance(Object... initargs)调用自己,传入参数!
22  */
23 public class TestStudent02 {
24     // 1.调用构造器得到一个类的对象返回。
25     @Test
26     public void getDeclaredConstructor() throws Exception {
27         // a.第一步:获取类对象
28         Class c = Student.class;
29         // b.定位单个构造器对象 (按照参数定位无参数构造器)
30         Constructor cons = c.getDeclaredConstructor();
31         System.out.println(cons.getName() + "===>" + cons.getParameterCount());
32 
33         // 如果遇到了私有的构造器,可以暴力反射
34         cons.setAccessible(true); // 权限被打开
35 
36         Student s = (Student) cons.newInstance();
37         System.out.println(s);
38 
39         System.out.println("-------------------");
40 
41         // c.定位某个有参构造器
42         Constructor cons1 = c.getDeclaredConstructor(String.class, int.class);
43         System.out.println(cons1.getName() + "===>" + cons1.getParameterCount());
44 
45         Student s1 = (Student) cons1.newInstance("孙悟空", 1000);
46         System.out.println(s1);
47     }
48 
49 
50 }
TestStudentDemo2

  6、利用反射技术获取成员变量的方式

    获取类中成员变量对象的方法

      getDeclaredFields()

      getDeclaredFiled(String name)

    

  7、反射得到成员变量可以做什么?

    依然是在某个对象中取值和赋值

      void set(Object obj,Object value)

      Object get(Object obj)

    

  8、如果某成员变量时非public的,需要打开权限(暴力反射),然后再取值、赋值

    setAccessible(boolean)

 1 package com.itheima.d4_reflect_field;
 2 
 3 public class Student {
 4     private String name;
 5     private int age;
 6     public static String schoolName;
 7     public static final String  COUNTTRY = "中国";
 8 
 9     public Student(){
10         System.out.println("无参数构造器执行!");
11     }
12 
13     public Student(String name, int age) {
14         System.out.println("有参数构造器执行!");
15         this.name = name;
16         this.age = age;
17     }
18 
19     public String getName() {
20         return name;
21     }
22 
23     public void setName(String name) {
24         this.name = name;
25     }
26 
27     public int getAge() {
28         return age;
29     }
30 
31     public void setAge(int age) {
32         this.age = age;
33     }
34 
35     @Override
36     public String toString() {
37         return "Student{" +
38                 "name='" + name + '\'' +
39                 ", age=" + age +
40                 '}';
41     }
42 }
Student
 1 package com.itheima.d4_reflect_field;
 2 
 3 import org.junit.Test;
 4 
 5 import java.io.File;
 6 import java.lang.reflect.Field;
 7 
 8 /**
 9      目标:反射_获取Field成员变量对象。
10 
11      反射的第一步是先得到Class类对象。
12 
13      1、Field getField(String name);
14             根据成员变量名获得对应Field对象,只能获得public修饰
15      2.Field getDeclaredField(String name);
16             根据成员变量名获得对应Field对象,只要申明了就可以得到
17      3.Field[] getFields();
18             获得所有的成员变量对应的Field对象,只能获得public的
19      4.Field[] getDeclaredFields();
20             获得所有的成员变量对应的Field对象,只要申明了就可以得到
21      小结:
22         获取全部成员变量:getDeclaredFields
23         获取某个成员变量:getDeclaredField
24  */
25 public class FieldDemo01 {
26     /**
27      * 1.获取全部的成员变量。
28      * Field[] getDeclaredFields();
29      *  获得所有的成员变量对应的Field对象,只要申明了就可以得到
30      */
31     @Test
32     public void getDeclaredFields(){
33         // a.定位Class对象
34         Class c = Student.class;
35         // b.定位全部成员变量
36         Field[] fields = c.getDeclaredFields();
37         // c.遍历一下
38         for (Field field : fields) {
39             System.out.println(field.getName() + "==>" + field.getType());
40         }
41     }
42 
43     /**
44         2.获取某个成员变量对象 Field getDeclaredField(String name);
45      */
46     @Test
47     public void getDeclaredField() throws Exception {
48         // a.定位Class对象
49         Class c = Student.class;
50         // b.根据名称定位某个成员变量
51         Field f = c.getDeclaredField("age");
52         System.out.println(f.getName() +"===>" + f.getType());
53     }
54 
55 }
FieldDemo1
 1 package com.itheima.d4_reflect_field;
 2 
 3 import org.junit.Test;
 4 
 5 import java.lang.reflect.Field;
 6 
 7 /**
 8     目标:反射获取成员变量: 取值和赋值。
 9 
10     Field的方法:给成员变量赋值和取值
11         void set(Object obj, Object value):给对象注入某个成员变量数据
12         Object get(Object obj):获取对象的成员变量的值。
13         void setAccessible(true);暴力反射,设置为可以直接访问私有类型的属性。
14         Class getType(); 获取属性的类型,返回Class对象。
15         String getName(); 获取属性的名称。
16  */
17 public class FieldDemo02 {
18     @Test
19     public void setField() throws Exception {
20         // a.反射第一步,获取类对象
21         Class c = Student.class;
22         // b.提取某个成员变量
23         Field ageF = c.getDeclaredField("age");
24 
25         ageF.setAccessible(true); // 暴力打开权限
26 
27         // c.赋值
28         Student s = new Student();
29         ageF.set(s , 18);  // s.setAge(18);
30         System.out.println(s);
31 
32         // d、取值
33         int age = (int) ageF.get(s);
34         System.out.println(age);
35 
36     }
37 }
FieldDemo2

  9、利用反射技术获取成员方法对象的方式

    获取类中成员方法对象

      getDeclaredMethods()

      getDeclaredMethod(String name,Class<?>...parameterTypes)

  10、反射得到成员方法可以做什么

    依然是在某个对象中触发该方法执行

      Object invoke(Object obj,Object...args)

    如果某成员方法是非public的,需要打开权限(暴力反射),然后再触发执行

      setAccessible(boolean)

 1 package com.itheima.d5_reflect_method;
 2 
 3 public class Dog {
 4     private String name ;
 5     public Dog(){
 6     }
 7 
 8     public Dog(String name) {
 9         this.name = name;
10     }
11 
12     public void run(){
13         System.out.println("狗跑的贼快~~");
14     }
15 
16     private void eat(){
17         System.out.println("狗吃骨头");
18     }
19 
20     private String eat(String name){
21         System.out.println("狗吃" + name);
22         return "吃的很开心!";
23     }
24 
25     public static void inAddr(){
26         System.out.println("在黑马学习Java!");
27     }
28 
29     public String getName() {
30         return name;
31     }
32 
33     public void setName(String name) {
34         this.name = name;
35     }
36 
37 }
Dog
 1 package com.itheima.d5_reflect_method;
 2 import org.junit.Test;
 3 
 4 import java.lang.reflect.Method;
 5 
 6 /**
 7     目标:反射——获取Method方法对象
 8 
 9     反射获取类的Method方法对象:
10          1、Method getMethod(String name,Class...args);
11              根据方法名和参数类型获得对应的方法对象,只能获得public的
12 
13          2、Method getDeclaredMethod(String name,Class...args);
14              根据方法名和参数类型获得对应的方法对象,包括private的
15 
16          3、Method[] getMethods();
17              获得类中的所有成员方法对象,返回数组,只能获得public修饰的且包含父类的
18 
19          4、Method[] getDeclaredMethods();
20             获得类中的所有成员方法对象,返回数组,只获得本类申明的方法。
21 
22     Method的方法执行:
23         Object invoke(Object obj, Object... args)
24           参数一:触发的是哪个对象的方法执行。
25           参数二: args:调用方法时传递的实际参数
26  */
27 public class MethodDemo01 {
28     /**
29      * 1.获得类中的所有成员方法对象
30      */
31     @Test
32     public void getDeclaredMethods(){
33         // a.获取类对象
34         Class c = Dog.class;
35         // b.提取全部方法;包括私有的
36         Method[] methods = c.getDeclaredMethods();
37         // c.遍历全部方法
38         for (Method method : methods) {
39             System.out.println(method.getName() +" 返回值类型:" + method.getReturnType() + " 参数个数:" + method.getParameterCount());
40         }
41     }
42 
43     /**
44      * 2. 获取某个方法对象
45      */
46     @Test
47     public void getDeclardMethod() throws Exception {
48         // a.获取类对象
49         Class c = Dog.class;
50         // b.提取单个方法对象
51         Method m = c.getDeclaredMethod("eat");
52         Method m2 = c.getDeclaredMethod("eat", String.class);
53 
54         // 暴力打开权限了
55         m.setAccessible(true);
56         m2.setAccessible(true);
57 
58         // c.触发方法的执行
59         Dog d = new Dog();
60         // 注意:方法如果是没有结果回来的,那么返回的是null.
61         Object result = m.invoke(d);
62         System.out.println(result);
63 
64         Object result2 = m2.invoke(d, "骨头");
65         System.out.println(result2);
66     }
67 }
MethodDemo01

  11、反射为何可以给约定了泛型的集合存入其他类型的元素?

    编译成Class文件进入运行阶段的时候,泛型会自动擦除

    反射是作用在运行时的技术,此时已经不存在泛型了

    泛型其实就只是规范我们的代码书写而已

    

    看下面的代码,突破我这只小菜鸡的想象

 1 package com.itheima.d6_reflect_genericity;
 2 
 3 import java.lang.reflect.Method;
 4 import java.util.ArrayList;
 5 
 6 public class ReflectDemo {
 7     public static void main(String[] args) throws Exception {
 8         // 需求:反射实现泛型擦除后,加入其他类型的元素
 9         ArrayList<String> lists1 = new ArrayList<>();
10         ArrayList<Integer> lists2 = new ArrayList<>();
11 
12         System.out.println(lists1.getClass());
13         System.out.println(lists2.getClass());
14 
15         System.out.println(lists1.getClass() ==  lists2.getClass());  // ArrayList.class
16 
17         System.out.println("---------------------------");
18         ArrayList<Integer> lists3 = new ArrayList<>();
19         lists3.add(23);
20         lists3.add(22);
21         // lists3.add("黑马");
22 
23         Class c = lists3.getClass(); // ArrayList.class  ===> public boolean add(E e)
24         // 定位c类中的add方法
25         Method add = c.getDeclaredMethod("add", Object.class);
26         boolean rs = (boolean) add.invoke(lists3, "黑马");
27         System.out.println(rs);
28 
29         System.out.println(lists3);
30 
31         ArrayList list4 = lists3;
32         list4.add("白马");
33         list4.add(false);
34         System.out.println(lists3);
35     }
36 }
ReflectDemo

  12、反射做通用框架之反射的作用

    可以在运行时得到一个类的全部成分然后操作

    可以破坏封装性(很突出)

    也可以破坏泛型的约束性(很突出)

    更重要的用途是适合:做Java高级框架

    基本上主流框架都会基于反射设计一些通用技术功能

  

 

 

   

 1 package com.itheima.d7_reflect_framework;
 2 
 3 public class Student {
 4     private String name;
 5     private char sex;
 6     private int age;
 7     private String className;
 8     private String hobby;
 9 
10     public Student(){
11 
12     }
13 
14     public Student(String name, char sex, int age, String className, String hobby) {
15         this.name = name;
16         this.sex = sex;
17         this.age = age;
18         this.className = className;
19         this.hobby = hobby;
20     }
21 
22     public String getName() {
23         return name;
24     }
25 
26     public void setName(String name) {
27         this.name = name;
28     }
29 
30     public char getSex() {
31         return sex;
32     }
33 
34     public void setSex(char sex) {
35         this.sex = sex;
36     }
37 
38     public int getAge() {
39         return age;
40     }
41 
42     public void setAge(int age) {
43         this.age = age;
44     }
45 
46     public String getClassName() {
47         return className;
48     }
49 
50     public void setClassName(String className) {
51         this.className = className;
52     }
53 
54     public String getHobby() {
55         return hobby;
56     }
57 
58     public void setHobby(String hobby) {
59         this.hobby = hobby;
60     }
61 }
Student
 1 package com.itheima.d7_reflect_framework;
 2 
 3 public class Teacher {
 4     private String name;
 5     private char sex;
 6     private double salary;
 7 
 8     public Teacher(){
 9 
10     }
11 
12     public Teacher(String name, char sex, double salary) {
13         this.name = name;
14         this.sex = sex;
15         this.salary = salary;
16     }
17 
18     public String getName() {
19         return name;
20     }
21 
22     public void setName(String name) {
23         this.name = name;
24     }
25 
26     public char getSex() {
27         return sex;
28     }
29 
30     public void setSex(char sex) {
31         this.sex = sex;
32     }
33 
34     public double getSalary() {
35         return salary;
36     }
37 
38     public void setSalary(double salary) {
39         this.salary = salary;
40     }
41 }
Teacher
 1 package com.itheima.d7_reflect_framework;
 2 
 3 import java.io.FileOutputStream;
 4 import java.io.PrintStream;
 5 import java.lang.reflect.Field;
 6 
 7 public class MybatisUtil {
 8     /**
 9      保存任意类型的对象
10      * @param obj
11      */
12     public static void save(Object obj){
13         try (
14                 PrintStream ps = new PrintStream(new FileOutputStream("junit-reflect-annotation-proxy-app/src/data.txt", true));
15         ){
16             // 1、提取这个对象的全部成员变量:只有反射可以解决
17             Class c = obj.getClass();  //   c.getSimpleName()获取当前类名   c.getName获取全限名:包名+类名
18             ps.println("================" + c.getSimpleName() + "================");
19 
20             // 2、提取它的全部成员变量
21             Field[] fields = c.getDeclaredFields();
22             // 3、获取成员变量的信息
23             for (Field field : fields) {
24                 String name = field.getName();
25                 // 提取本成员变量在obj对象中的值(取值)
26                 field.setAccessible(true);
27                 String value = field.get(obj) + "";
28                 ps.println(name  + "=" + value);
29             }
30         } catch (Exception e) {
31             e.printStackTrace();
32         }
33     }
34 }
MybatisUtil
 1 package com.itheima.d7_reflect_framework;
 2 
 3 import java.util.Date;
 4 import java.util.Properties;
 5 
 6 /**
 7    目标:提供一个通用框架,支持保存所有对象的具体信息。
 8  */
 9 public class ReflectDemo {
10     public static void main(String[] args) throws Exception {
11         Student s = new Student();
12         s.setName("猪八戒");
13         s.setClassName("西天跑路1班");
14         s.setAge(1000);
15         s.setHobby("吃,睡");
16         s.setSex('男');
17         MybatisUtil.save(s);
18 
19         Teacher t = new Teacher();
20         t.setName("波仔");
21         t.setSex('男');
22         t.setSalary(6000);
23         MybatisUtil.save(t);
24     }
25 }
View Code

第三节   注解

  1、注解的作用

    对Java中类、方法、成员变量做标记,然后进行特殊处理

    例如:Junit框架中,标记了注解@Test的方法就可以被当成测试方法执行,而没有标记的就不能当成测试方法执行

    

 

 

     

  2、自定义注解

    

 

 

     

 

 

1 package com.itheima.d8_annotation;
2 
3 public @interface Book {
4     String value(); // 特殊属性
5     double price() ;
6     //double price() default 9.9;
7 }
Book
1 package com.itheima.d8_annotation;
2 
3 public @interface MyBook {
4     String name();
5     String[] authors();
6     double price();
7 }
MyBook
 1 package com.itheima.d8_annotation;
 2 
 3 /**
 4    目标:学会自定义注解。掌握其定义格式和语法。
 5  */
 6 @MyBook(name="《精通JavaSE》",authors = {"黑马", "dlei"} , price = 199.5)
 7 //@Book(value = "/delete")
 8 // @Book("/delete")
 9 @Book(value = "/delete", price = 23.5)
10 //@Book("/delete")
11 public class AnnotationDemo1 {
12 
13     @MyBook(name="《精通JavaSE2》",authors = {"黑马", "dlei"} , price = 199.5)
14     private AnnotationDemo1(){
15 
16     }
17 
18     @MyBook(name="《精通JavaSE1》",authors = {"黑马", "dlei"} , price = 199.5)
19     public static void main(String[] args) {
20         @MyBook(name="《精通JavaSE2》",authors = {"黑马", "dlei"} , price = 199.5)
21         int age = 21;
22     }
23 }
AnnotationDemo1

  3、元注解是什么

    注解注解的注解

    @Target约束自定义注解可以标记的范围

    @Retention用来约束自定义注解的存活范围,就是注解的生命周期

    

  4、注解解析的方式

    

    ==================================================================================================

    

 

 

     =============================================================================================

    

 

 

 

 1 package com.itheima.d8_annotation;
 2 
 3 import java.lang.annotation.ElementType;
 4 import java.lang.annotation.Retention;
 5 import java.lang.annotation.RetentionPolicy;
 6 import java.lang.annotation.Target;
 7 
 8 @Target({ElementType.TYPE,ElementType.METHOD})
 9 @Retention(RetentionPolicy.RUNTIME)
10 public @interface Bookk {
11     String value();
12     double price() default 100;
13     String[] author();
14 }
Bookk
 1 package com.itheima.d8_annotation;
 2 
 3 import org.junit.Test;
 4 
 5 import java.lang.annotation.Annotation;
 6 import java.lang.reflect.Method;
 7 import java.util.Arrays;
 8 
 9 /**
10    目标:完成注解的解析
11  */
12 public class AnnotationDemo3 {
13     @Test
14     public void parseClass(){
15         // a.先得到类对象
16         Class c = BookStore.class;
17         // b.判断这个类上面是否存在这个注解
18         if(c.isAnnotationPresent(Bookk.class)){
19             //c.直接获取该注解对象
20             Bookk book = (Bookk) c.getDeclaredAnnotation(Bookk.class);
21             System.out.println(book.value());
22             System.out.println(book.price());
23             System.out.println(Arrays.toString(book.author()));
24         }
25     }
26 
27     @Test
28     public void parseMethod() throws NoSuchMethodException {
29         // a.先得到类对象
30         Class c = BookStore.class;
31 
32         Method m = c.getDeclaredMethod("test");
33 
34         // b.判断这个类上面是否存在这个注解
35         if(m.isAnnotationPresent(Bookk.class)){
36             //c.直接获取该注解对象
37             Bookk book = (Bookk) m.getDeclaredAnnotation(Bookk.class);
38             System.out.println(book.value());
39             System.out.println(book.price());
40             System.out.println(Arrays.toString(book.author()));
41         }
42     }
43 }
44 
45 @Bookk(value = "《情深深雨濛濛》", price = 99.9, author = {"琼瑶", "dlei"})
46 class BookStore{
47 
48     @Bookk(value = "《三少爷的剑》", price = 399.9, author = {"古龙", "熊耀华"})
49     public void test(){
50     }
51 }
AnnotationDemo3

  5、模拟Junit框架

    

 1 package com.itheima.d8_annotation;
 2 
 3 import java.lang.reflect.InvocationTargetException;
 4 import java.lang.reflect.Method;
 5 
 6 public class AnnotationDemo4 {
 7     public void test1(){
 8         System.out.println("===test1===");
 9     }
10 
11     @MyTest
12     public void test2(){
13         System.out.println("===test2===");
14     }
15 
16     @MyTest
17     public void test3(){
18         System.out.println("===test3===");
19     }
20 
21     /**
22       启动菜单:有注解的才被调用。
23      */
24     public static void main(String[] args) throws Exception {
25         AnnotationDemo4 t = new AnnotationDemo4();
26         // a.获取类对象
27         Class c = AnnotationDemo4.class;
28         // b.提取全部方法
29         Method[] methods = c.getDeclaredMethods();
30         // c.遍历方法,看是否有MyTest注解,有就跑它
31         for (Method method : methods) {
32             if(method.isAnnotationPresent(MyTest.class)){
33                 // 跑它
34                 method.invoke(t);
35             }
36         }
37     }
38 }
View Code

第四节   动态代理

  1、代理是什么

    一个对象,用来对被代理对象的行为额外做一些辅助工作

  2、在Java中实现动态代理的步骤是什么样的

    必须存在接口

    被代理对象需要实现接口

    使用Proxy类提供的方法,的对象的代理对象

    

  3、通过代理对象调用方法,执行流程是什么样的

    先走向代理

    代理可以为方法额外做一些辅助工作

    开发真正触发对象的方法的执行

    回到代理中,由代理负责返回结果给方法的调用者

  

 

   

  ===========================================================================================

  

 

   

 1 package com.itheima.d9_proxy;
 2 
 3 /**
 4    模拟用户业务功能
 5  */
 6 public interface UserService {
 7     String login(String loginName , String passWord) ;
 8     void selectUsers();
 9     boolean deleteUsers();
10     void updateUsers();
11 }
UserService
 1 package com.itheima.d9_proxy;
 2 
 3 public class UserServiceImpl implements UserService{
 4     @Override
 5     public String login(String loginName, String passWord)  {
 6         try {
 7             Thread.sleep(1000);
 8         } catch (Exception e) {
 9             e.printStackTrace();
10         }
11         if("admin".equals(loginName) && "1234".equals(passWord)) {
12             return "success";
13         }
14         return "登录名和密码可能有毛病";
15 
16     }
17 
18     @Override
19     public void selectUsers() {
20         System.out.println("查询了100个用户数据!");
21         try {
22             Thread.sleep(2000);
23         } catch (Exception e) {
24             e.printStackTrace();
25         }
26     }
27 
28     @Override
29     public boolean deleteUsers() {
30         try {
31             System.out.println("删除100个用户数据!");
32             Thread.sleep(500);
33             return true;
34         } catch (Exception e) {
35             e.printStackTrace();
36             return false;
37         }
38     }
39 
40     @Override
41     public void updateUsers() {
42         try {
43             System.out.println("修改100个用户数据!");
44             Thread.sleep(2500);
45         } catch (Exception e) {
46             e.printStackTrace();
47         }
48     }
49 }
UserServiceImp
 1 package com.itheima.d9_proxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 import java.lang.reflect.Proxy;
 6 /**
 7     public static Object newProxyInstance(ClassLoader loader,  Class<?>[] interfaces, InvocationHandler h)
 8     参数一:类加载器,负责加载代理类到内存中使用。
 9     参数二:获取被代理对象实现的全部接口。代理要为全部接口的全部方法进行代理
10     参数三:代理的核心处理逻辑
11  */
12 public class ProxyUtil {
13     /**
14       生成业务对象的代理对象。
15      * @param obj
16      * @return
17      */
18     public static <T> T  getProxy(T obj) {
19         // 返回了一个代理对象了
20         return (T)Proxy.newProxyInstance(obj.getClass().getClassLoader(),
21                 obj.getClass().getInterfaces(),
22                 new InvocationHandler() {
23                     @Override
24                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
25                         // 参数一:代理对象本身。一般不管
26                         // 参数二:正在被代理的方法
27                         // 参数三:被代理方法,应该传入的参数
28                        long startTimer = System .currentTimeMillis();
29                         // 马上触发方法的真正执行。(触发真正的业务功能)
30                         Object result = method.invoke(obj, args);
31 
32                         long endTimer = System.currentTimeMillis();
33                         System.out.println(method.getName() + "方法耗时:" + (endTimer - startTimer) / 1000.0 + "s");
34 
35                         // 把业务功能方法执行的结果返回给调用者
36                         return result;
37                     }
38                 });
39     }
40 }
ProxyUtil
 1 package com.itheima.d9_proxy;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5         // 1、把业务对象,直接做成一个代理对象返回,代理对象的类型也是 UserService类型
 6         UserService userService = ProxyUtil.getProxy(new UserServiceImpl());
 7         System.out.println(userService.login("admin", "1234"));
 8         System.out.println(userService.deleteUsers());
 9         userService.selectUsers();
10         userService.updateUsers(); // 走代理
11     }
12 }
Test
posted @ 2022-09-19 16:27  漫漫修行路  阅读(125)  评论(0)    收藏  举报