目录
前言
java高级技术笔记复盘【完】
一、单元测试
就是针对最小的功能单元(方法),编写测试代码对其进行正确性测试。
咱们之前是如何进行单元测试的?有啥问题?
- 只能在main方法编写测试代码,去调用其他方法进行测试。
- 无法实现自动化测试,一个方法测试失败,可能影响其他方法的测试。
- 无法得到测试的报告,需要程序员自己去观察测试是否成功。
Junit单元测试框架
优点
- 可以灵活的编写测试代码,可以针对某个方法执行测试,也支持一键完成对全部方法的自动化测试,且各自独立
- 不需要程序员去分析测试的结果,会自动生成测试报告出来
1.1 Junit单元测试-快速入门
需求
- 某个系统,有多个业务方法,请使用Junit单元测试框架,编写测试代码,完成对这些方法的正确性测试。
具体步骤
- 将Junit框架的jar包导入到项目中(注意:IDEA集成了Junit框架,不需要我们自己手工导入了)
- 为需要测试的业务类,定义对应的测试类,并为每个业务方法,编写对应的测试方法(必须:公共、无参、无返回值)
- 测试方法上必须声明@Test注解,然后在测试方法中,编写代码调用被测试的业务方法进行测试;
- 开始测试:选中测试方法,右键选择“JUnit运行”,如果测试通过则是绿色;如果测试失败,则是红色
StringUtilTest.class
package com.ithema.d1_junit;
import org.junit.Assert;
import org.junit.Test;
//测试类
public class StringUtilTest {
@Test
//必须是公开的方法,且是无返回值,无参数的 测试方法, 否则会出bug。方法名建议前面加test并采用驼峰命名的方法。 上面加@Test注解
public void testPrintNumber(){
StringUtil.printNumber("nihao");
StringUtil.printNumber(null);
}
@Test
public void testGetMaxIndex(){
int index1=StringUtil.getMaxIndex("nihao");
System.out.println(index1);
int index2=StringUtil.getMaxIndex(null);
System.out.println(index2);
//断言机制:程序员可以通过预测业务方法的结果
Assert.assertEquals("方法内部有bug",4,index1);
}
}
printNumber.class
package com.ithema.d1_junit;
//字符串工具类
public class StringUtil {
public static void printNumber(String name){
if(name==null){
System.out.println(0);
return;//停掉方法
}
System.out.println("名字的长度是:"+name.length());
}
//求字符串的最大索引
public static int getMaxIndex(String data){
if(data==null){
return -1;
}
return data.length()-1;
}
}
1.2 Junit框架的常见注解
- 在测试方法执行前执行的方法,常用于:初始化资源。
- 在测试方法执行完后再执行的方法,常用于:释放资源。
StringUtil.class
package com.ithema.d1_junit;
//字符串工具类
public class StringUtil {
public static void printNumber(String name){
if(name==null){
System.out.println(0);
return;//停掉方法
}
System.out.println("名字的长度是:"+name.length());
}
//求字符串的最大索引
public static int getMaxIndex(String data){
if(data==null){
return -1;
}
return data.length()-1;
}
}
StringUtilTest.class
package com.ithema.d1_junit;
import org.junit.*;
//测试类
public class StringUtilTest {
//BeforeClass 和 AfterClass 必须是静态的测试方法
@BeforeClass
public static void test11(){
System.out.println("================================================================BeforeClass test11被执行了==============================================================="+'\n');
}
@AfterClass
public static void test12(){
System.out.println("================================================================AfterClass test12被执行了==============================================================="+'\n');
}
@Before
public void test1(){
System.out.println("================================================================Before test1被执行了==============================================================="+'\n');
}
@After
public void test2(){
System.out.println("================================================================After test2被执行了==============================================================="+'\n');
}
@Test
//必须是公开的方法,且是无返回值,无参数的 测试方法, 否则会出bug。方法名建议前面加test并采用驼峰命名的方法。 上面加@Test注解
public void testPrintNumber(){
StringUtil.printNumber("nihao");
StringUtil.printNumber(null);
}
@Test
public void testGetMaxIndex(){
int index1=StringUtil.getMaxIndex("nihao");
System.out.println(index1);
int index2=StringUtil.getMaxIndex(null);
System.out.println(index2);
//断言机制:程序员可以通过预测业务方法的结果
Assert.assertEquals("方法内部有bug",4,index1);
}
}
二、反射
2.1 认识反射、获取类
反射:就是加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)
获取Class对象的三种方式:
- Classc1=类名.class
- 调用Class提供方法:public staticClass forName(String package);
- Object提供的方法:publicClass getClass();Class c3=对象.getClass();
Test1Class.class
package com.itheima.d2_reflect;
public class Test1Class {
public static void main(String[] args) throws Exception {
Class c1=Student.class;
System.out.println(c1.getName());//全类名
System.out.println(c1.getSimpleName());//简名 Student
Class c2 = Class.forName("com.itheima.d2_reflect.Student");
System.out.println(c1 == c2);
Student s=new Student();
Class c3= s.getClass();
System.out.println(c3 == c2);
}
}
Student.class
package com.itheima.d2_reflect;
public class Student {
}
2.2 获取类的构造器
获取类构造器的作用:依然是初始化一个对象返回
Cat.class
package com.itheima.d2_reflect;
public class Cat {
private String name;
private int age;
private Cat() {
}
public Cat(String name, int age) {
this.name = name;
this.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;
}
}
Test2Constructor.class
package com.itheima.d2_reflect;
import org.junit.Test;
import java.lang.reflect.Constructor;
public class Test2Constructor {
@Test
public void testGetConstructors() throws Exception {
// 1、反射第一步:必须先得到这个类的Class对象
Class c = Cat.class;
// 2、获取类的全部构造器
//只能获取公共的public的构造器
//Constructor [] constructors = c.getConstructors();
//可以获得包括私有的全部构造器
Constructor[] constructors = c.getDeclaredConstructors();
//3、遍历数组中的每个构造器对象
for (Constructor constructor : constructors) {
System.out.println(constructor.getName() + "---->" + constructor.getParameterCount());
}
}
@Test
public void testGetConstructor() throws Exception {
// 1、反射第一步:必须先得到这个类的Class对象
Class c = Cat.class;
// 2、获取某个构造器:无参数构造器
//只能获取公共的public的构造器
// Constructor constructor=c.getConstructor();
Constructor constructor = c.getDeclaredConstructor();
System.out.println(constructor.getName() + "===========>" + constructor.getParameterCount());
//3、获取有参数构造器
Constructor constructor2 = c.getDeclaredConstructor(String.class, int.class);
System.out.println(constructor2.getName() + "===========>" + constructor2.getParameterCount());
}
}
Cat.class
package com.itheima.d2_reflect;
public class Cat {
private String name;
private int age;
private Cat() {
System.out.println("无参数构造器执行了");
}
public Cat(String name, int age) {
this.name = name;
this.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;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Test2Constructor.class
package com.itheima.d2_reflect;
import org.junit.Test;
import java.lang.reflect.Constructor;
public class Test2Constructor {
@Test
public void testGetConstructors() throws Exception {
// 1、反射第一步:必须先得到这个类的Class对象
Class c = Cat.class;
// 2、获取类的全部构造器
//只能获取公共的public的构造器
//Constructor [] constructors = c.getConstructors();
//可以获得包括私有的全部构造器
Constructor[] constructors = c.getDeclaredConstructors();
//3、遍历数组中的每个构造器对象
for (Constructor constructor : constructors) {
System.out.println(constructor.getName() + "---->" + constructor.getParameterCount());
}
}
@Test
public void testGetConstructor() throws Exception {
// 1、反射第一步:必须先得到这个类的Class对象
Class c = Cat.class;
// 2、获取某个构造器:无参数构造器
//只能获取公共的public的构造器
// Constructor constructor1=c.getConstructor();
Constructor constructor1 = c.getDeclaredConstructor();
System.out.println(constructor1.getName() + "===========>" + constructor1.getParameterCount());
constructor1.setAccessible(true);//禁止检査访问权限
Cat cat = (Cat) constructor1.newInstance();
System.out.println(cat);
//3、获取有参数构造器
Constructor constructor2 = c.getDeclaredConstructor(String.class, int.class);
System.out.println(constructor2.getName() + "===========>" + constructor2.getParameterCount());
constructor1.setAccessible(true);//禁止检査访问权限
Cat cat1 = (Cat) constructor2.newInstance("叮当猫",3);
System.out.println(cat1);
}
}
2.3 获取类的成员变量
Cat.class
package com.itheima.d2_reflect;
public class Cat {
public static int a;
public static final String COUNTRY="中国";
private String name;
private int age;
private Cat() {
System.out.println("无参数构造器执行了");
}
public Cat(String name, int age) {
this.name = name;
this.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;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Test3Field.class
package com.itheima.d2_reflect;
import org.junit.Test;
import java.lang.reflect.Field;
public class Test3Field {
@Test
public void testGetFiled() throws Exception {
//1、反射第一步:必须是先得到类的Class对参
Class c = Cat.class;
//2、获取类的全部成员变量。
Field[] fields = c.getDeclaredFields();
//3、遍历这个成员变量数组
for (Field field : fields) {
System.out.println(field.getName() + "===============>" + field.getType());
}
//4、定位某个成员变量
Field fName=c.getDeclaredField("name");
System.out.println(fName.getName() + "===============>" + fName.getType());
Field fAge=c.getDeclaredField("age");
System.out.println(fAge.getName() + "===============>" + fAge.getType());
}
}
获取到成员变量的作用:依然是赋值、取值。
Test3Field.class
package com.itheima.d2_reflect;
import org.junit.Test;
import java.lang.reflect.Field;
public class Test3Field {
@Test
public void testGetFiled() throws Exception {
//1、反射第一步:必须是先得到类的Class对参
Class c = Cat.class;
//2、获取类的全部成员变量。
Field[] fields = c.getDeclaredFields();
//3、遍历这个成员变量数组
for (Field field : fields) {
System.out.println(field.getName() + "===============>" + field.getType());
}
//4、定位某个成员变量
Field fName = c.getDeclaredField("name");
System.out.println(fName.getName() + "===============>" + fName.getType());
Field fAge = c.getDeclaredField("age");
System.out.println(fAge.getName() + "===============>" + fAge.getType());
//赋值
Cat cat = new Cat();
fName.setAccessible(true);// 禁止访问控制权限
fName.set(cat, "加菲猫");
fAge.setAccessible(true);// 禁止访问控制权限
fAge.set(cat, 3);
System.out.println(cat);
//取值
String name = (String) fName.get(cat);
System.out.println(name);
Integer age = (Integer) fAge.get(cat);
System.out.println(age);
}
}
2.4 获取类的成员方法
Cat.class
package com.itheima.d2_reflect;
public class Cat {
public static int a;
public static final String COUNTRY = "中国";
private String name;
private int age;
public Cat() {
System.out.println("无参数构造器执行了");
}
private void run() {
System.out.println("🐱跑的快");
}
public void eat() {
System.out.println("🐱吃的多");
}
private String eat(String name) {
return "🐱吃的多" + name;
}
public Cat(String name, int age) {
this.name = name;
this.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;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
TestGetMethods.class
package com.itheima.d2_reflect;
import org.junit.Test;
import java.lang.reflect.Method;
public class Test4Method {
@Test
public void testGetMethods() throws Exception {
//1、反射第一步:必须是先得到类的Class对参
Class c = Cat.class;
//2、获取类的全部成员方法。
Method[] methods = c.getDeclaredMethods();
//3、遍历这个数组中的每个方法对象
for (Method method : methods) {
System.out.println(method.getName()+"---->"
+method.getParameterCount()+
"---->"+method.getReturnType());
}
//获取某个方法的对象
Method run=c.getDeclaredMethod("run");//拿run方法 且 无参数
System.out.println(run.getName()+"---->"
+run.getParameterCount()+
"---->"+run.getReturnType());
Method eat=c.getDeclaredMethod("eat",String.class);//拿run方法 且 无参数
System.out.println(eat.getName()+"---->"
+eat.getParameterCount()+
"---->"+eat.getReturnType());
}
}
成员方法的作用:依然是执行
Test4Method.class
package com.itheima.d2_reflect;
import org.junit.Test;
import java.lang.reflect.Method;
public class Test4Method {
@Test
public void testGetMethods() throws Exception {
//1、反射第一步:必须是先得到类的Class对参
Class c = Cat.class;
//2、获取类的全部成员方法。
Method[] methods = c.getDeclaredMethods();
//3、遍历这个数组中的每个方法对象
for (Method method : methods) {
System.out.println(method.getName()+"---->"
+method.getParameterCount()+
"---->"+method.getReturnType());
}
//获取某个方法的对象
Method run=c.getDeclaredMethod("run");//拿run方法 且 无参数
System.out.println(run.getName()+"---->"
+run.getParameterCount()+
"---->"+run.getReturnType());
Method eat=c.getDeclaredMethod("eat",String.class);//拿run方法 且 无参数
System.out.println(eat.getName()+"---->"
+eat.getParameterCount()+
"---->"+eat.getReturnType());
Cat cat=new Cat();
run.setAccessible(true);//禁止检查访问权限
Object rs=run.invoke(cat);//调用无参数的run方法,用cat对象触发调用
System.out.println(rs);
eat.setAccessible(true);//禁止检查访问权限
String rs2= (String) eat.invoke(cat,"🐟");
System.out.println(rs2);
}
}
2.5 作用、应用场景
反射的作用?
- 基本作用:可以得到一个类的全部成分然后操作
- 可以破坏封装性
- 最重要的用途是:适合做Java的框架,基本上,主流的框架都会基于反射设计出一些通用的功能。
实现步骤
- 定义一个方法,可以接收任意对象。
- 每收到一个对象后,使用反射获取该对象的Class对象,然后获取全部的成员变量
- 遍历成员变量,然后提取成员变量在该对象中的具体值。
- 把成员变量名、和其值,写出到文件中去即可。
Student.class
package com.itheima.d2_reflect;
public class Student {
private String name;
private int age;
private char sex;
private double height;
private String hobby;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
", height=" + height +
", hobby='" + hobby + '\'' +
'}';
}
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;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public Student() {
}
public Student(String name, int age, char sex, double height, String hobby) {
this.name = name;
this.age = age;
this.sex = sex;
this.height = height;
this.hobby = hobby;
}
}
Teacher.class
package com.itheima.d2_reflect;
public class Teacher {
private String name;
private double salary;
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", salary=" + salary +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Teacher() {
}
public Teacher(String name, double salary) {
this.name = name;
this.salary = salary;
}
}
ObjectFrame.class
package com.itheima.d2_reflect;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
public class ObjectFrame {
// 目标:保存任意对象的字段和其数据到文件中去
public static void saveObject(Object obj) throws Exception {
PrintStream ps = new PrintStream(new FileOutputStream("D:\\code\\javasepro\\junit-reflect-annotation-proxy-app\\src\\data.txt", true));
//1、obj是任意对象,到底有多少个字段要保存。
Class c = obj.getClass();
String cName = c.getSimpleName();
ps.println("---------------------------" + cName + "------------------");
//2、从这个类中提取它的全部成员变量
Field[] fields = c.getDeclaredFields();
//3、遍历每个成员变量
for (Field field : fields) {
//4、拿到成员变量的每个名字
String name = field.getName();
//5、拿到这个成员变量在对象中的数据
field.setAccessible(true);//禁止检查访问控制
String value = field.get(obj) + " ";
ps.println(name + " = " + value);
}
ps.close();
}
}
TestFrame.class
package com.itheima.d2_reflect;
import org.junit.Test;
public class Test5Frame {
@Test
public void save() throws Exception {
Student s1 = new Student("张三", 45, '男', 180.2, "打游戏");
Teacher t1 = new Teacher("李四", 1922.02);
//需求:把任意对象的字段名和其对应的值等信息,保存到文件中去。
ObjectFrame.saveObject(s1);
ObjectFrame.saveObject(t1);
}
}
三、注解
3.1 概述、自定义注解
注解(Annotation)
- 就是Java代码里的特殊标记,比如:@Override、@Test等
- 作用是:让其他程序根据注解信息来决定怎么执行该程序
- 注意:注解可以用在类上、构造器上、方法上、成员变量上、参数上、等位置处
自定义注解
- 就是自己定义注解
MyTest.Annotation
package com.itheima.d3_Annotation;
public @interface MyTest1 {
String aaa();
boolean bbb() default true;
String[] ccc();
}
AnntationTest.class
package com.itheima.d3_Annotation;
@MyTest1(aaa = "张三", ccc = {"HTML,JAVA"})
public class AnnotationTest1 {
@MyTest1(aaa = "李四", bbb = false, ccc = {"Python", "前端", "Java"})
public void test1() {
}
}
特殊属性名: value
- 如果注解中只有一个value属性,使用注解时,value名称可以不写!!
MyTest2.class
package com.itheima.d3_Annotation;
public @interface MyTest2 {
String value();//特殊属性
}
AnntationTest.class
package com.itheima.d3_Annotation;
@MyTest1(aaa = "张三", ccc = {"HTML,JAVA"})
//@MyTest2(value = "王五")
@MyTest2("王五")
public class AnnotationTest1 {
@MyTest1(aaa = "李四", bbb = false, ccc = {"Python", "前端", "Java"})
public void test1() {
}
}
- 注解本质是一个接口,Java中所有注解都是继承了Annotation接口的
- @注解(...):其实就是一个实现类对象,实现了该注解以及Annotation接口。
3.2 元注解
指的是:修饰注解的注解
MyTest.Annotation
package com.itheima.d3_Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.METHOD})// 当前被修饰的注解只能用在类和方法上。
public @interface MyTest3 {
}
AnntationTest.class
package com.itheima.d3_Annotation;
@MyTest3()
public class AnnotationTest2 {
@MyTest3()
public void test(){
}
}
3.3 注解的解析
什么是注解的解析?
就是判断类上、方法上、成员变量上是否存在注解,并把注解里的内容给解析出来
如何解析注解?
- 指导思想:要解析谁上面的注解,就应该先拿到谁。
- 比如要解析类上面的注解,则应该先获取该类的Class对象,再通过Class对象解析其上面的注解
- 比如要解析成员方法上的注解,则应该获取到该成员方法的Method对象,再通过Method对象解析其上面的注解。
- Class、Method、Field,Constructor、都实现了AnnotatedElement接口,它们都拥有解析注解的能力。
MyTets4.Annotation
package com.itheima.d3_Annotation;
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 MyTest4 {
String value();
double aaa() default 100;
String[] bbb();
}
Demo.class
package com.itheima.d3_Annotation;
@MyTest4(value = "蜘蛛精",aaa=99.5,bbb={"至尊宝","张三"})
public class Demo {
@MyTest4(value = "孙悟空",aaa=199.9,bbb={"紫霞","李四"})
public void test1(){
}
}
AnnotationTest3.class
package com.itheima.d3_Annotation;
import org.junit.Test;
import java.lang.reflect.Method;
import java.util.Arrays;
public class AnnotationTest3 {
@Test
public void parseClass() {
//1、先得到Class对象
Class c = Demo.class;
//2、解析类上的注解
//判断这个类上是否包含了某个注解
//判断这个类上是否包含了这个类的类型
if(c.isAnnotationPresent(MyTest4.class)){
MyTest4 myTest4 = (MyTest4) c.getDeclaredAnnotation(MyTest4.class);
System.out.println(myTest4.value());
System.out.println(myTest4.aaa());
System.out.println(Arrays.toString(myTest4.bbb()));
}
}
@Test
public void parseMethod() throws Exception {
//1、先得到Class对象
Class c = Demo.class;
Method m = c.getDeclaredMethod("test1");
//2、解析方法上的注解
//判断这个方法上是否包含了某个注解
//判断这个方法上是否包含了这个方法的类型
if (c.isAnnotationPresent(MyTest4.class)) {
MyTest4 myTest4 = (MyTest4) c.getDeclaredAnnotation(MyTest4.class);
System.out.println(myTest4.value());
System.out.println(myTest4.aaa());
System.out.println(Arrays.toString(myTest4.bbb()));
}
}
}
3.4 应用场景
MyTest.Annotation
package com.itheima.d3_Annotation;
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 {
}
AnnotationTest4.class
package com.itheima.d3_Annotation;
import java.lang.reflect.Method;
public class AnnotationTest4 {
// @MyTest
public void test1() {
System.out.println("=======test1=======");
}
@MyTest
public void test2() {
System.out.println("=======test2=======");
}
// @MyTest
public void test3() {
System.out.println("=======test3=======");
}
@MyTest
public void test4() {
System.out.println("=======test4=======");
}
public static void main(String[] args) throws Exception {
AnnotationTest4 a = new AnnotationTest4();
//启动程序
//1、得到Class对象
Class c = AnnotationTest4.class;
//2、提取这个类中的全部成员方法
Method[] methods = c.getDeclaredMethods();
//3、遍历数组中的每个方法,看方法上是否存在MyTest注解,如果存在触发该方法执行
for (Method method : methods) {
if (method.isAnnotationPresent(MyTest.class)) {
//说明当前方法上存在@MyTest,触发当前方法执行
method.invoke(a);
}
}
}
}
四、动态代理
4.1 程序为什么需要代理?代理长什么样?
Start.interface
package com.itheima.d4_proxy;
public interface Start {
String sing(String name);
void dance();
}
BigStart.class
package com.itheima.d4_proxy;
public class BigStart implements Start {
private String name;
public BigStart(String name) {
this.name = name;
}
public String sing(String name) {
System.out.println(this.name + "正在唱:" + name);
return "谢谢! 谢谢!";
}
public void dance() {
System.out.println(this.name + "正在优美的跳舞~~");
}
}
ProxyUtil.class
package com.itheima.d4_proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyUtil {
public static Start createProxy(BigStart bigStart) {
//选择反射下的Proxy类
/*
* ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h
*
* 参数1:用于指定一个加载器
* 参数2:指定生成的代理长什么样子,也就是有哪些方法
* 参数3:用来指定生成的代理对象要干什么事情
* */
//
Start startProxy = (Start) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[]{Start.class},
new InvocationHandler() {
@Override// 回调方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//代理对象要做的事情,会在这里写代码
if (method.getName().equals("sing")) {
System.out.println("准备话筒");
return method.invoke(bigStart, args);
} else if (method.getName().equals("dance")) {
System.out.println("准备场地");
return method.invoke(bigStart, args);
} else {
return method.invoke(bigStart, args);
}
}
});
return startProxy;
}
}
Test.class
package com.itheima.d4_proxy;
public class Test {
public static void main(String[] args) {
BigStart s = new BigStart("zhang san");
Start startProxy = ProxyUtil.createProxy(s);
String rs = startProxy.sing("好日子");
System.out.println(rs);
startProxy.dance();
}
}
4.2 解决实际问题、掌握使用代理的好处
UserService.interface
package com.itheima.d5_proxy2;
public interface UserService {
//登录功能
void login(String loginName, String passWord) throws Exception;
//删除用户
void deleteUsers() throws Exception;
//查询用户,返回数组形式
String[] selectUsers() throws Exception;
}
UserSerivceImpl.class
package com.itheima.d5_proxy2;
public class UserServiceImpl implements UserService {
@Override
public void login(String loginName, String passWord) throws Exception {
if ("admin".equals(loginName) && "123456".equals(passWord)) {
System.out.println("您登录成功!");
} else {
System.out.println("您登录失败!");
}
Thread.sleep(1000);
}
@Override
public void deleteUsers() throws Exception {
System.out.println("成功删除了1万个用户~");
Thread.sleep(1500);
}
@Override
public String[] selectUsers() throws Exception {
System.out.println("查询除了3个用户:");
String[] names = {"张三", "李四", "王五"};
Thread.sleep(500);
return names;
}
}
ProxyUtil.class
package com.itheima.d5_proxy2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyUtil {
public static UserService createProxy(UserService userService) {
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
new Class[]{UserService.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("login") || method.getName().equals("deleteUsers") || method.getName().equals("selectUsers")) {
long startTime = System.currentTimeMillis();
Object rs = method.invoke(userService, args);
long endTime = System.currentTimeMillis();
System.out.println(method.getName() + "当前方法执行了:" + (endTime - startTime) / 1000.0 + "s");
return rs;
} else {
Object rs = method.invoke(userService, args);
return rs;
}
}
});
return userServiceProxy;
}
}
Test.class
package com.itheima.d5_proxy2;
import java.util.Arrays;
public class Test {
public static void main(String[] args) throws Exception {
//1、创建用户业务对象。
UserService userService = ProxyUtil.createProxy(new UserServiceImpl());
// 2、调用用户业务的功能。
userService.login("admin", "123456");
System.out.println("==================================================================");
userService.deleteUsers();
System.out.println("==================================================================");
String[] names = userService.selectUsers();
System.out.println("查询到的用户是:" + Arrays.toString(names));
System.out.println("==================================================================");
}
}