day30-java

单元测试

单元测试就是针对最小的功能单元编写测试代码,Java程序最小的功能单元是方法,因此,单元测试就是针对Java方法的测试,进而检查方法的正确性。

JUnit单元测试框架

JUnit是使用Java语言实现的单元测试框架,它是开源的,Java开发者都应当学习并使用JUnit编写单元测试。
此外,几乎所有的IDE工具都集成了JUnit,这样我们就可以直接在IDE中编写并运行JUnit测试,JUnit目前最新版本是5。

JUnit的优点

JUnit可以灵活的选择执行哪些测试方法,可以一键执行全部测试方法。
Junit可以生成全部方法的测试报告。
单元测试中的某个方法测试失败了,不会影响其他测试方法的测试,等等。

测试类
package com.ithaima.d1_Junit;

import org.junit.*;

/**
 * 测试类
 */
public class TestUserService {
    /**
     * @Before修饰实例方法,在每个测试方法执行之前先执行一次
     * 可用于初始化资源,如io流
     * Junit5改名为BeforeEach
     */
    @Before
    public void before(){
        System.out.println("before方法执行一次");
    }

    /**
     * @After修饰实例方法,在每个测试方法执行之后执行一次
     * 可用于关闭资源,如关闭io流
     * Junit5改名为AfterEach
     */
    @After
    public void after(){
        System.out.println("after方法执行一次");
    }

    /**
     * @BeforeClass修饰静态方法,在所有测试方法执行之前执行一次
     * 可用于初始化静态资源
     * Junit5后改名BeforeAll
     */
    @BeforeClass
    public static void beforeClass(){
        System.out.println("beforeClass执行一次");
    }

    /**
     * @AfterClass修饰静态方法,在所有测试方法执行之后执行一次
     * 可用于关闭静态资源
     * Junit5后改名AfterAll
     */
    @AfterClass
    public static void afterClass(){
        System.out.println("afterClass执行一次");
    }

    /**
     * 测试方法
     * 测试方法必须是无参无返回值且公开的实例方法
     * 红色失败,绿色成功
     */
    @Test
    public void TestLogin(){
        //创建业务方法类对象
        UserService u = new UserService();
        //调用login方法
        String rs = u.login("admin", "123456");
        
        /*
        参数一:实际返回值与预期返回值不符时的提示信息
        参数二:预期返回值
        参数三:实际返回值
        比较预期结果与实际结果,不同则给出
        */
        Assert.assertEquals("登录业务可能出问题了","登录成功",rs);
    }
    /*
    测试业务方法类中的print方法
    */
    @Test
    public void TestPrint(){
        UserService u = new UserService();
        u.print();
    }
}
业务方法
package com.ithaima.d1_Junit;

/**
 * 业务方法
 */
public class UserService {

    public String login(String name, String pwd){
        if ("admin".equals(name)&&"123456".equals(pwd)){
            return "登录成功";
        }else{
            return "用户名或密码有问题";
        }
    }
    
    public void print(){
        System.out.println(10/0);
        System.out.println("天青色等烟雨,而我在等你.");
    }
}

反射

通过反射获取Class类对象

测试类

package com.ithaima.d2_reflect.reflect1_class;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取Class类对象,方式一:forName(全类名),全类名:包名+类名
        Class c = Class.forName("com.ithaima.d2_reflect.reflect1_class.Student");

        //方式二:类名.class
        Class c1 = Student.class;

        //方式三:对象名.getClass
        Class c2 = new Student().getClass();
    }
}

class Student{}

通过反射获取构造器

测试类

package com.ithaima.d2_reflect.reflect2_constructor;


import org.junit.Test;

import java.lang.reflect.Constructor;

public class TestStudent{
    /**
     * 获取所有public构造器对象
     */
    @Test
    public void TestGetConstructors(){
        //创建Class类对象
        Class c = Student.class;
        //获取构造器
        Constructor[] constructors = c.getConstructors();
        for (Constructor constructor : constructors) {
            //遍历输出构造器及其参数个数
            System.out.println(constructor+"-->"+constructor.getParameterCount());
        }
    }

    /**
     * 获取所有构造器对象,包括私有的
     */
    @Test
    public void TestGetDeclaredConstructors(){
        Class c = Student.class;
        Constructor[] constructors = c.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor+"-->"+constructor.getParameterCount());
        }
    }
    /**
     * 获取一个指定的public修饰的构造器对象
     */
    @Test
    public void TestGetConstructor() throws NoSuchMethodException {
        Class c = Student.class;
        Constructor constructor = c.getConstructor();
        System.out.println(constructor+"-->"+constructor.getParameterCount());
    }
    /**
     * 获取一个指定的构造器对象,包括私有的
     */
    @Test
    public void TestGetDeclaredConstructor() throws Exception {
        Class c = Student.class;
        Constructor constructor = c.getDeclaredConstructor();
        System.out.println(constructor+"-->"+constructor.getParameterCount());
        
        //学生类的无参构造器是私有的,需要解除权限,暴力反射,破环了封装性,私有亦可执行
        constructor.setAccessible(true);
        //使用获取的构造器创建学生对象
        Student stu1 = (Student) constructor.newInstance();
        System.out.println(stu1);

        //获取有参构造器,传入参数类型
        Constructor dc = c.getDeclaredConstructor(String.class, int.class);
        Student stu2 = (Student) dc.newInstance("张三", 22);
        System.out.println(stu2);
    }
}

学生类

package com.ithaima.d2_reflect.reflect2_constructor;

public class Student {
    private String name;
    private int age;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    private Student() {
        System.out.println("无参构造器执行了");
    }

    public Student(String name, int age) {
        System.out.println("有参构造器执行了");
        this.name = name;
        this.age = age;
    }
}

通过反射获取字段

测试类

package com.ithaima.d2_reflect.reflect3_field;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/**
 * getField()
 * getFields()
 * getDeclaredField()
 * getDeclaredFields()
 */
public class TestGetConstructorField {
    @Test
    public void testGetDeclaredFields() throws Exception {
        Class<Student> sc = Student.class;
        //获取所有成员变量
        Field[] dfs = sc.getDeclaredFields();
        for (Field df : dfs) {
            //输出成员变量名及其类型
            System.out.println(df.getName()+df.getType());
        }
        //通过变量名获取指定成员变量
        Field age = sc.getDeclaredField("age");
        //获取无参构造器,给定泛型后使用该构造器创建学生对象不需要强转型
        Constructor<Student> dc = sc.getDeclaredConstructor();
        //暴力反射
        dc.setAccessible(true);
        //创建对象
        Student stu = dc.newInstance();
        //打开权限
        age.setAccessible(true);
        //赋值
        age.set(stu,18);
        //获取age字段在对象stu中的值
        int a = (int)age.get(stu);
        System.out.println(a);
        System.out.println(stu);
    }
}

学生类

package com.ithaima.d2_reflect.reflect3_field;

public class Student {
    private String name;
    private int age;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    private Student() {
        System.out.println("无参构造器执行了");
    }

    public Student(String name, int age) {
        System.out.println("有参构造器执行了");
        this.name = name;
        this.age = age;
    }
}

通过反射获取方法

测试类

package com.ithaima.d2_reflect.reflect4_method;

import org.junit.Test;

import java.lang.reflect.Method;

public class MethodDemo {
    @Test
    public void testGetDeclaredMethods() throws Exception {
        Class<Dog> c = Dog.class;
        Method[] dms = c.getDeclaredMethods();
        for (Method dm : dms) {
            System.out.println(dm+" 返回类型:"+dm.getReturnType());
        }
        //获取无参的eat方法
        Method eat = c.getDeclaredMethod("eat");
        Dog dog = new Dog();
        //暴力打开权限
        eat.setAccessible(true);
        //调用dog对象的eat方法
        eat.invoke(dog);

        //获取有参的eat方法
        Method eat1 = c.getDeclaredMethod("eat", String.class);
        //暴力打开权限
        eat1.setAccessible(true);
        //调用dog对象的有参eat方法,接收返回值
        String s = (String) eat1.invoke(dog, "骨头");
        System.out.println(s);
    }

}

Dog类

package com.ithaima.d2_reflect.reflect4_method;

public class Dog {
    private String name;

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

    public Dog() {
    }

    private void eat(){
        System.out.println("狗吃骨头");
    }

    private String eat(String food){
        System.out.println("狗吃"+food);
        return "so happy!";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

反射的应用

向集合中添加泛型约束之外的元素

案例
package com.ithaima.d2_reflect.reflect5_app;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 使用反射向集合中添加非泛型约束的元素
 * 反射是作用在运行时的技术,当类被编译成字节码文件进入运行阶段后,泛型就被擦除了
 */
public class AppDemo01 {
    public static void main(String[] args) throws Exception {
        ArrayList<Integer> list = new ArrayList<>();
        ArrayList<String> lists = new ArrayList<>();

        //class java.util.ArrayList
        System.out.println(list.getClass());
        System.out.println(lists.getClass());

        //true,说明编译后所有ArrayList都存放在同一个字节码文件中
        System.out.println(list.getClass() == lists.getClass());

        System.out.println("----------------------------------------");
        ArrayList<Integer> list1 = new ArrayList<>(List.of(30,4,23,89));
        Class lc = list1.getClass();
        Method add = lc.getDeclaredMethod("add", Object.class);
        boolean b = (boolean) add.invoke(list1, "黑马");
        System.out.println(list1);
        System.out.println(b);

        ArrayList list2 = list1;
        list2.add("白马");
        System.out.println(list1);
    }
}

做通用框架

测试类
package com.ithaima.d2_reflect.reflect5_app;

public class AppDemo02 {
    public static void main(String[] args) {
        Student s = new Student();
        s.setName("猪八戒");
        s.setClassName("西天跑路1班");
        s.setAge(1000);
        s.setHobby("吃,睡");
        s.setSex('男');
        MyBatis.save(s);

        Teacher t = new Teacher();
        t.setName("波仔");
        t.setSex('男');
        t.setSalary(6000);
        MyBatis.save(t);
    }
}
MyBatis类
package com.ithaima.d2_reflect.reflect5_app;

import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;

/**
 * 利用反射做通用框架
 * 实现接收任意类型数据对象
 * 存储到文件中去
 */
public class MyBatis {
    /**
     * 存储任意数据类型对象
     * @param o
     */
    public static void save(Object o){
        try(
                PrintStream ps = new PrintStream(new FileOutputStream("day13-Junit-reflect-annotation-proxy\\src\\com\\ithaima\\d2_reflect\\reflect5_app\\object.txt",true))
                ) {
            //获取对象的类对象
            Class c = o.getClass();
            //getSimpleName:获取类名,getName:获取全类名
            ps.println("==============="+c.getSimpleName()+"==============");
            //获取类对象的所有字段
            Field[] dfs = c.getDeclaredFields();
            //遍历所有字段
            for (Field df : dfs) {
                //获取字段名
                String name = df.getName();
                //暴力打开权限,获取成员变量在对象o中的值
                df.setAccessible(true);
                String value = df.get(o)+"";
                //存储字段
                ps.println(name+"="+value);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
object.txt
===============Student==============
name=猪八戒
sex=男
age=1000
className=西天跑路1班
hobby=吃,睡
===============Teacher==============
name=波仔
sex=男
salary=6000.0

Student类
package com.ithaima.d2_reflect.reflect5_app;

public class Student {
    private String name;
    private char sex;
    private int age;
    private String className;
    private String hobby;

    public Student(){

    }

    public Student(String name, char sex, int age, String className, String hobby) {
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.className = className;
        this.hobby = hobby;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }
}
Teacher类
package com.ithaima.d2_reflect.reflect5_app;

public class Teacher {
    private String name;
    private char sex;
    private double salary;

    public Teacher(){

    }

    public Teacher(String name, char sex, double salary) {
        this.name = name;
        this.sex = sex;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}

注解

Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。
Java 语言中的类、构造器、方法、成员变量、参数等都可以被注解进行标注。

注解的作用

对Java中类、方法、成员变量做标记,然后进行特殊处理,至于到底做何种处理由业务需求来决定。
例如:JUnit框架中,标记了注解@Test的方法就可以被当成测试方法执行,而没有标记的就不能当成测试方法执行。

自定义注解

MyBook注解

package com.ithaima.d3_annotation.annotation1_custom;

/**
 * 自定义注解
 * 使用@interface修饰
 * 属性格式:public 类型 属性名() default 默认值;
 * 可以不给定默认值
 */
public @interface MyBook {
    //public可省略
    public String name();
    String[] authors();
    double price();
}

测试类

package com.ithaima.d3_annotation.annotation1_custom;

/**
 * 可对类  方法  变量做注解
 */
@MyBook(name = "学习Java",authors = {"shifan","李四"},price = 200)
public class Demo01 {
    @MyBook(name = "学习Java",authors = {"shifan","李四"},price = 200)
    public static void main(String[] args) {
        @MyBook(name = "学习Java",authors = {"shifan","李四"},price = 200)
        int a = 10;
    }
}

特殊属性value

Book注解
package com.ithaima.d3_annotation.annotation1_custom;

/**
 * 特殊属性:value
 * 当注解中只有value这一个属性时
 * 使用注解的时候value可省略
 * 而仅当存在多个属性,且其他属性都有默认值时,value才可省略
 */
public @interface Book {
    String value();
    double price() default 200;
}
测试类
package com.ithaima.d3_annotation.annotation1_custom;

import com.ithaima.d3_annotation.annotation2_meta.MyTest;

//@Book("/delete")
//有默认值的属性可省略不写
@Book("/delete")
//@MyTest,无法标记类
public class Demo02 {
    @MyTest
    public static void main(String[] args) {

    }
}

元注解

注解注解的注解

MyTest注解

package com.ithaima.d3_annotation.annotation2_meta;

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

/**
 * 元注解
 * 用来注解注解的注解
 * 常见的有@Target 约束注解可标记的位置
 * 其参数有:
 * ElementType.Type  类,接口
 * ElementType.METHOD  成员方法
 * ElementType.FIELD  成员变量
 * ElementType.PARAMETER  方法参数
 * ElementType.CONSTRUCTOR  构造器
 * ElementType.LOCAL_VARIABLE  局部变量
 * @Retention  约束注解的存活时间
 * 其参数有:
 * RetentionPolicy.RUNTIME  注解从源码 字节码一直到运行时都存在
 * RetentionPolicy.CLASS  注解在源码 字节码阶段都存在,运行阶段不存在
 * RetentionPolicy.SOURCE  注解仅在源码阶段存在, 字节码和运行阶段不存在
 */
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {

}

测试类

package com.ithaima.d3_annotation.annotation2_meta;

//@MyTest,无法标记类
public class Demo02 {
    @MyTest
    public static void main(String[] args) {
    }
}

注解的解析

相关接口

Annotation: 注解的顶级接口,注解都是Annotation类型的对象
AnnotatedElement:该接口定义了与注解解析相关的解析方法

AnnotatedElement的解析方法

Annotation[] getDeclaredAnnotations() 获得当前对象上使用的所有注解,返回注解数组。

T getDeclaredAnnotation(Class annotationClass) 根据注解类型获得对应注解对象

boolean isAnnotationPresent(Class annotationClass) 判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false

所有的类成分Class, Method , Field , Constructor,都实现了AnnotatedElement接口他们都拥有解析注解的能力

解析注解的技巧

注解在哪个成分上,我们就先拿哪个成分对象。
比如注解作用成员方法,则要获得该成员方法对应的Method对象,再来拿上面的注解
比如注解作用在类上,则要该类的Class对象,再来拿上面的注解
比如注解作用在成员变量上,则要获得该成员变量对应的Field对象,再来拿上面的注解

Book注解

package com.ithaima.d3_annotation.annotation3_parse;

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

//对自定义注解进行注解
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Book {
    String name();
    double price() default 200;
    String[] authors();
}

测试类

package com.ithaima.d3_annotation.annotation3_parse;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 解析注解
 * getDeclaredAnnotations() 获取所有注解
 */
public class TestDemo {
    public static void main(String[] args) throws NoSuchMethodException {
        //解析类的注解
        //1.获取BookStore类的类对象
        Class<BookStore> c = BookStore.class;
        //判断类是否存在Book注解
        if (c.isAnnotationPresent(Book.class)) {
            //获取注解对象
            Book da = c.getDeclaredAnnotation(Book.class);
            //输出注解的属性
            System.out.println(da.name());
            System.out.println(da.price());
            System.out.println(Arrays.toString(da.authors()));
        }
        //解析方法的注解
        //1.获取BookStore类的类对象
        Class<BookStore> c1 = BookStore.class;
        //2.获取book方法
        Method book = c1.getDeclaredMethod("book");
        //判断类是否存在Book注解
        if (book.isAnnotationPresent(Book.class)) {
            //获取注解对象
            Book da = book.getDeclaredAnnotation(Book.class);
            //输出注解的属性
            System.out.println(da.name());
            System.out.println(da.price());
            System.out.println(Arrays.toString(da.authors()));
        }
    }
}

@Book(name="《斗破苍穹》",price = 100,authors = {"天蚕土豆","时帆"})
class BookStore{
    @Book(name="《斗破苍穹》",price = 100,authors = {"天蚕土豆","时帆"})
    public void book(){

    }
}

模拟JUnit框架

MyTest注解

package com.ithaima.d3_annotation.annotation4_simulateJUnit;

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.ithaima.d3_annotation.annotation4_simulateJUnit;

import java.lang.reflect.Method;

/**
 * 模拟JUnit框架
 * 只有加了@MyTest注解的方法才能被执行
 */
public class TestDemo {
    public void test1(){
        System.out.println("----test1----");
    }
    @MyTest
    public void test2(){
        System.out.println("----test2----");
    }
    @MyTest
    public void test3(){
        System.out.println("----test3----");
    }

    /**
     * 启动菜单
     * @param args
     */
    public static void main(String[] args) {
        TestDemo td = new TestDemo();

        //1.获取类对象
        Class<TestDemo> tdc = TestDemo.class;

        //2.获取所有方法对象
        Method[] methods = tdc.getDeclaredMethods();

        //3.遍历对象数组执行带有@MyTest注解的方法
        for (Method method : methods) {
            if (method.isAnnotationPresent(MyTest.class)){
                try {
                    method.invoke(td);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

动态代理

代理就是被代理者没有能力或者不愿意去完成某件事情,需要找个人代替自己去完成这件事,动态代理就是用来对业务功能(方法)进行代理的。

关键步骤

1.必须有接口,实现类要实现接口(代理通常是基于接口实现的)。
2.创建一个实现类的对象,该对象为业务对象,紧接着为业务对象做一个代理对象。

动态代理的优点

非常的灵活,支持任意接口类型的实现类对象做代理,也可以直接为接本身做代理。
可以为被代理对象的所有方法做代理。
可以在不改变方法源码的情况下,实现对方法功能的增强。
不仅简化了编程工作、提高了软件系统的可扩展性,同时也提高了开发效率。

案例:模拟企业业务功能,统计功能性能

业务接口类

package com.ithaima.d4_proxy;

public interface UserService {
    String login(String name,String pwd);
    boolean deleteUsers();
    void searchUsers();
}

业务功能类1

package com.ithaima.d4_proxy;

public class UserServicempl1 implements UserService {
    @Override
    public String login(String name, String pwd) {
        long start = System.currentTimeMillis();
        try {
            Thread.sleep(1000);
            if ("admin".equals(name)&&"123".equals(pwd)){
                return "success";
            }else {
                return "用户名或密码错误";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "error";
        } finally {
            long end = System.currentTimeMillis();
            System.out.println("login方法执行时间:"+(end-start)/1000.0+"s");
        }
    }

    @Override
    public boolean deleteUsers() {
        long start = System.currentTimeMillis();
        try {
            Thread.sleep(500);
            System.out.println("删除了100个用户");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            long end = System.currentTimeMillis();
            System.out.println("deleteUsers方法执行时间:"+(end-start)/1000.0+"s");
        }
    }

    @Override
    public void searchUsers() {
        long start = System.currentTimeMillis();
        try {
            Thread.sleep(2000);
            System.out.println("查询了100个用户");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            long end = System.currentTimeMillis();
            System.out.println("searchUsers方法执行时间:"+(end-start)/1000.0+"s");
        }
    }
}

测试类

package com.ithaima.d4_proxy;

/**
 * 模拟企业业务功能并做性能分析
 */
public class Test {
    public static void main(String[] args) {
        //单独对每个方法做性能分析
        UserService us1 = new UserServicempl1();
        System.out.println(us1.deleteUsers());
        System.out.println(us1.login("admin", "123"));
        us1.searchUsers();
    }
}

使用代理做功能的性能分析

代理工具类

package com.ithaima.d4_proxy;

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

public class ProxyUtil {

    //使用泛型实现为任意接口类型的实现类对象做代理,也可直接为接口做代理
    public static<T> T getProxy(T obj) {
        /*
        public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
          参数一:类加载器,负责加载代理类到内存中使用
          参数二:被代理对象实现的所有接口,代理要为所有接口的所有方法进行代理
          参数三:代理的核心处理逻辑
         */
        return (T)Proxy.newProxyInstance(UserServicempl2.class.getClassLoader(), UserServicempl2.class.getInterfaces(), new InvocationHandler() {
            /*
            参数一:代理对象本身,一般不管
            参数二:当前被代理触发执行的方法
            参数三:当前方法的参数列表
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                long start = System.currentTimeMillis();
                //触发执行业务方法
                Object result = method.invoke(obj, args);
                long end = System.currentTimeMillis();
                System.out.println(method.getName()+"方法执行时间:"+(end-start)/1000.0+"s");
                //返回业务方法的执行结果
                return result;
            }
        });
/*
        return (UserService)Proxy.newProxyInstance(UserServicempl2.class.getClassLoader(), UserServicempl2.class.getInterfaces(), new InvocationHandler() {
            */
/*
            参数一:代理对象本身,一般不管
            参数二:当前被代理触发执行的方法
            参数三:当前方法的参数列表
             *//*

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                long start = System.currentTimeMillis();
                //触发执行业务方法
                Object result = method.invoke(obj, args);
                long end = System.currentTimeMillis();
                System.out.println(method.getName()+"方法执行时间:"+(end-start)/1000.0+"s");
                //返回业务方法的执行结果
                return result;
            }
        });
*/
/*        return (UserService)Proxy.newProxyInstance(UserServicempl2.class.getClassLoader(), UserServicempl2.class.getInterfaces(),
                ( proxy, method, args)-> {
                long start = System.currentTimeMillis();
                //触发执行业务方法
                Object result = method.invoke(obj, args);
                long end = System.currentTimeMillis();
                System.out.println(method.getName()+"方法执行时间:"+(end-start)/1000.0+"s");
                //返回业务方法的执行结果
                return result;});*/
    }
}

业务功能类2

package com.ithaima.d4_proxy;

public class UserServicempl2 implements UserService {
    @Override
    public String login(String name, String pwd) {
        try {
            Thread.sleep(1000);
            if ("admin".equals(name)&&"123".equals(pwd)){
                return "success";
            }else {
                return "用户名或密码错误";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "error";
        }
    }

    @Override
    public boolean deleteUsers() {
        try {
            Thread.sleep(500);
            System.out.println("删除了100个用户");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public void searchUsers() {
        try {
            Thread.sleep(2000);
            System.out.println("查询了100个用户");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

测试类

package com.ithaima.d4_proxy;

/**
 * 模拟企业业务功能并做性能分析
 */
public class Test {
    public static void main(String[] args) {
        //单独对每个方法做性能分析
        UserService us1 = new UserServicempl1();
        System.out.println(us1.deleteUsers());
        System.out.println(us1.login("admin", "123"));
        us1.searchUsers();

        /**
         * 单独对每个方法做性能分析代码重复严重
         * 业务逻辑不够清晰
         */
        //使用代理做性能分析
        //把业务对象做成一个代理对象返回,代理对象也是UserService类型
        UserService us2 = ProxyUtil.getProxy(new UserServicempl2());
        us2.searchUsers();
        us2.login("admin","123");
        us2.deleteUsers();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值