单元测试
单元测试就是针对最小的功能单元编写测试代码,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();
}
}