Java

学习内容

单元测试 反射 注解 动态代理
开发好的系统中存在很多的方法,如和对这些方法的正确性进行测试 如何在程序运行时取得到Class对象,然后取获得Class中的每个成分 注解是什么,具体是如何在Java程序中解决问题的? 框架技术的底层会用到的

单元测试

概述

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

当前测试方法,存在问题

  • 只有一个main方法,如果一个方法的测试失败了,其他方法测试会受影响
  • 无法得到测试的结果报告,需要程序员自己取观察测试是否成功
  • 无法实现自动化测试

JUnit单元测试框架

  • JUnit是使用Java语言实现的单元测试框架,它是开源的,Java开发者都应当去学习JUnit编写单元测试
  • 此外,几乎所有的IDE工具都集成了JUnit,这样我们就可以直接在IDE中编写并运行JUnit测试,Junit目前最新版本是5
JUnit优点
  • JUnit可以灵活的选择执行哪些测试方法,可以一键执行全部测试方法
  • JUnit可以生成全部方法的测试报告
  • 单元测试中的某个方法测试失败了,不会影响其他测试方法的测试
JUnit单元测试作用
  • 测试类方法的正确性
总结
  1. JUnit单元测试的实现过程是什么样的

    • 必须导入JUnit框架的jar包
    • 定义的测试方法必须是无参数返回值,且公开的方法
    • 测试方法使用@Test注解标记
  2. JUnit测试某个方法,测试全部方法怎么处理?成功的标志是什么
    • 测试莫格方法直接右键该方法启动测试
    • 测试全部方法,可以选择类或者模块启动
    • 红色失败,绿色通过

JUnit常用注解(JUnit 4.xxx版本)

注解 说明
@Test 测试方法
@Bfore 用来修饰实例方法,该方法会在每一个测试方法执行之前执行一次
@After 用来修饰实例方法,该方法会在每一个测试方法执行之后执行一次
@BeforeClass 用来静态修饰方法,该方法会在所有测试方法之前只执行一次
@AfterClass 用来静态修饰方法,该方法会在所有测试方法之后只执行一次
  • 开始执行的方法:初始化资源
  • 执行完之后的方法:释放资源

JUnit常用注解(JUnit 5.xxx版本)

注解 说明
@Test 测试方法
@BforeEach 用来修饰实例方法,该方法会在每一个测试方法执行之前执行一次
@AfterEach 用来修饰实例方法,该方法会在每一个测试方法执行之后执行一次
@BeforeAll 用来静态修饰方法,该方法会在所有测试方法之前只执行一次
@AfterAll 用来静态修饰方法,该方法会在所有测试方法之后只执行一次
  • 开始执行的方法:初始化资源
  • 执行完之后的方法:释放资源

反射

概述

  • 反射是对于任何一个Class类,在“运行的时候”都可以直接得到这个类的全部成分
  • 在运行时,可以直接得到这个类的构造器对象:Constructor
  • 在运行时,可以直接得到这个类的成员变量:Field
  • 在运行时,可以直接得到这个类的成员方法对象:Method
  • 这种运动时动态获取类信息以及动态调用类中成分的能力称为Java语言的反射机制
反射的关键:
  • 反射的第一步都是先得到编译后的Class类对象,然后就可以得到Class的全部成分

    HelloWorld.java->javac->HelloWorld.Class
    Class c = HelloWorld.class
总结
  • 反射的基本作用、关键?

    • 反射是在运行是获取类的字节码文件对象:然后可以解析类中的全部成分
    • 反射的核心思想和关键就:得到编译以后的class文件对象

反射获取类对象

反射第一步:获取Class类的对象
方法一:Class类中静态方法
  • 源代码阶段

    1. forName(String className)
方法二:Class对象阶段
    1. 类名.class
方法三:Runtime运行时阶段
    1. 对象.getClass()

反射获取构造器对象

使用反射技术获取构造器对象并使用
  • 反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。
Class类中用于获取构造器的方法
方法 什么
Constructor<?> getConstructors() 返回所有构造器对象的数组(只拿public的)
Constructor<?> getDeclaredConstructors() 返回所有构造器对象的数组,存在就能拿到
Constructor getConstructor(Class<?>...ParameterTypes) 返回单个构造器对象(只能拿public)
Constructor getDeclaredConstructor(Class<?> ...parameterTypes) 返回单个构造器对象,存在就能拿到
package com.yu.Day1013Demo.Constructor;

import org.junit.Test;

import java.lang.reflect.Constructor;

public class TestStudent {
//1.getConstructor
@Test
public void getConstructors(){
//a.第一步,获取类对象
Class c = Student.class;
//b.获取类中的全部的构造器对象
Constructor[] constructors = c.getConstructors();
//c.遍历构造器
for (Constructor constructor : constructors) {
System.out.println(constructor.getName()+"-->"+constructor.getParameterCount());
}
}
//2.getDeclaredConstructors()
@Test
public void getDeclaredConstructors(){
//a.第一步,获取类对象
Class c = Student.class;
//b.获取类中的全部的构造器对象
Constructor[] constructors = c.getDeclaredConstructors();
//c.遍历构造器
for (Constructor constructor : constructors) {
System.out.println(constructor.getName()+"-->"+constructor.getParameterCount());
}
}
//3.getConstructor(Class...paramenterTypes)
@Test
public void getConstructor() throws Exception {
//a.第一步,获取类对象
Class c = Student.class;
//b.获取类中的全部的构造器对象(按照参数定位无参数构造器)
Constructor constructor = c.getConstructor(String.class,int.class);
//c.输出
System.out.println(constructor.getName()+"-->"+constructor.getParameterCount()); }
//4.getDeclaredConstructor(Class...paramenterTypes)
@Test
public void getDeclaredConstructor() throws Exception {
//a.第一步,获取类对象
Class c = Student.class;
//b.获取类中的全部的构造器对象(按照参数定位无参数构造器)
Constructor constructor = c.getConstructor();
//c.输出
System.out.println(constructor.getName()+"-->"+constructor.getParameterCount()); }
}
package com.yu.Day1013Demo.Constructor;

public class Student {
private String name;
private int age; public Student(String name, int age) {
this.name = name;
this.age = age;
} private Student() {
} @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;
} }
Constructor类中用于创建对象的方法
方法 说明
T newInstance(Object... initargs) 根据指定的构造器创建对象
public void setAccessible(boolean flag) 设置true,表示取消访问检查,进行暴力反射
package com.yu.Day1013Demo.Constructor;

import org.junit.Test;

import java.lang.reflect.Constructor;

public class TestStudent01 {
//a.第一步获取类对象
@Test
public void getDeclaredConstructor() throws Exception {
//a.第一步,获取类对象
Class c = Student.class;
//b.获取类中的全部的构造器对象(按照参数定位无参数构造器)
Constructor constructor = c.getDeclaredConstructor();
//c.输出
System.out.println(constructor.getName()+"-->"+constructor.getParameterCount());
//如果遇到了私有构造器,可以暴力反射
constructor.setAccessible(true);
//无参构造器
Student s = (Student)constructor.newInstance();
System.out.println(s);
//有参构造器
Constructor cons1 = c.getDeclaredConstructor(String.class,int.class);
System.out.println(cons1.getName()+"-->"+cons1.getParameterCount());
Student s1 = (Student)cons1.newInstance("孙悟空",1000);
System.out.println(s1); }
}
总结
  1. 利用反射技术获取构造器对象的方式

    • getDeclaredConstructors()
    • getDeclaredConstructor(Class<?> ...parameterTypes)
  2. 反射得到的构造器可以做什么?
    • 依然是创建对象的

      • public newInstance(Object...initargs)
    • 如果是分public的构造器,需要打开权限(暴力反射),然后再创建对象
      • setAccessible(boolean)
      • 反射可以破环封装性,私有的也可以执行了

反射获取成员变量对象

使用反射技术获取成员变量对象并使用
  • 反射第一步先得到类对象,然后从类对象中获取类的成分对象
  • Class类中用于获取成员变量的方法
方法 说明
Field[] getFields() 返回所有成员变量对象的数组(只拿public的)
Field[] getDeclaredFields() 返回所有成员变量对象的数组,存在就能拿到
Field getField(String name) 返回单个成员变量对象(只能拿public的)
Field getDeclareField(String name) 返回单个成员变量对象,存在就能拿到
  • 获取成员变量的作用依然是再某个对象中取值、赋值
Field类中用于取值、赋值的方法
方法
void set(Object obj,Object value) 赋值
Object get(Object obj) 取值
总结
  1. 利用反射技术获取成员变量的方式

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

      • getDeclaredFields()
      • getDeclaredField()
  2. 反射得到成员变量可以做什么
    • 依然是再某个对象中取值和赋值

      • void set(Object obj,Object value)
      • Objcet get(Object obj)
    • 如果某成员变量是非public的,需要打开权限(暴力反射),然后再取值、赋值
      • setAccessible(boolean)
package com.yu.Day1013Demo.Field.Constructor;

public class Student {
private String name;
private int age;
public static String schoolName;
public static final String COUNTTER = "中国"; public Student(String name, int age) {
this.name = name;
this.age = age;
} public Student() {
} @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;
} }
package com.yu.Day1013Demo.Field.Constructor;

import org.junit.Test;

import java.lang.reflect.Field;

public class FieldDemo01 {
@Test
public void getDeclaredFields(){
//a.定位Class对象
Class c = Student.class;
//b. 定位全部成员变量
Field[] fields = c.getDeclaredFields();
//c.变量输出
for (Field field : fields) {
System.out.println(field.getName()+"--->"+field.getType());
}
}
@Test
public void getDeclaredField() throws Exception{
//a.定位Class对象
Class c = Student.class;
//b. 定位全部成员变量
Field f = c.getDeclaredField("age");
//c.变量输出
System.out.println(f.getName()+"--->"+f.getType());
}
}
package com.yu.Day1013Demo.Field.Constructor;

import org.junit.Test;

import java.lang.reflect.Field;

public class FieldDemo02 {
@Test
public void setField() throws Exception{
Class c = Student.class;
Field f = c.getDeclaredField("age"); Student s = new Student();
f.setAccessible(true);
f.set(s,18);;
System.out.println(s);
}
}

反射获取方法对象

  • 反射的第一步是先得到类对象,然后从类对象中获取类的成分对象
  • Class类中用于获取成员方法的方法
方法 说明
Method[] getMethods() 返回所有成员方法对象的数组(只能拿public的)
Method[] getDeclaredMethods() 返回所有成员方法对象的数组,存在就能拿到
Method getMethod(String name,Class<?>...parameterTypes) 返回单个成员方法对象(只能拿public的)
Method getDeclaredMethod(String name,Class<?>...parameterTypes) 返回单个成员方法对象,存在就能拿到
Method类中用于触发执行的方法
方法 说明
Object invoke(Object obj,Objcet...args) 运行方法
参数一:用obj对象调用该方法
参数二:调用方法传递的参数(如果没有则不写)
参数三:方法返回值(没有则不写)
总结
  1. 利用反射技术获取成员方法对象的方式

    • 获取类中成员方法对象

      • getDeclaredMethods()
      • getDeclaredMethod(Sting name,Class<?> ... parameterTypes)
  2. 反射得到成员方法可以做什么
    • 依然是在某个对象中触发该方法执行

      • Object invoke(Object obj,Objcet..args)
    • 如果某成员方法是非public的,需要权限(暴力反射),然后再触发执行
      • setAccessible(boolean)
package com.yu.Day1013Demo.method;

public class Dog {
private String name;
public Dog(){
} public Dog(String name) {
this.name = name;
}
private void eat(){
System.out.println("狗吃骨头");
}
private String eat(String name){
System.out.println("狗吃"+name);
return "吃的很开心";
}
public static void inAddr(){
System.out.println("在黑马学习java");
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
package com.yu.Day1013Demo.method;

import org.junit.Test;

import java.lang.reflect.Method;

public class MethodDemo01 {
//获取全方法
@Test
public void getDeclaredMethods(){
Class c = Dog.class;
Method[] methods = c.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName()+"返回值类型"+method.getReturnType()+"参数个数"+method.getParameterCount());
}
}
//获取某一个方法
@Test
public void getDeclaredMethod() throws Exception{
Class c = Dog.class;
Method method = c.getDeclaredMethod("eat");
Method method2 = c.getDeclaredMethod("eat",String.class);
method.setAccessible(true);
method2.setAccessible(true);
Dog d = new Dog();
//不带参数
Object result = method.invoke(d);
System.out.println(result);
//带参数
Object resulf2 = method2.invoke(d,"骨头");
System.out.println(resulf2);
}
}

反射作用-绕过编译阶段为集合添加数据

  • 反射的作用在运行是的技术,此时集合的泛型将不能产生约束了,此时是可以为集合存入其他类型的元素的
ArrayList<Integet> list = new ArrayList<>();
list.add(100);
//list.add("黑马");//报错
list.add(99);
  • 泛型只是在编译阶段可以约束集合只能操作魔种数据类型,在编译成Class文件进入运行阶段的时候,其真实类型都是ArrayList了,泛型相当于被擦除了。
package com.yu.Day1013Demo.genericity;

import java.lang.reflect.Method;
import java.util.ArrayList; public class ReflectDemo {
public static void main(String[] args) throws Exception{
ArrayList<String> list1 = new ArrayList<>();
ArrayList<Integer> list2 = new ArrayList<>(); System.out.println(list1.getClass());
System.out.println(list2.getClass()); System.out.println(list1.getClass()==list2.getClass()); System.out.println("--------------------------------");
list2.add(222);
list2.add(111);
//llist2.add("黑马");
Class c = list2.getClass();
//定位c类中的add方法
Method add = c.getDeclaredMethod("add",Object.class);
boolean rs = (boolean)add.invoke(list2,"黑啊吗");
System.out.println(rs);
System.out.println(list2); }
}
总结
  1. 反射为什么可以给约定了泛型的集合存入其他类型的元素?

    • 编译成Class文件进入运行阶段的时候,泛型会自动解除
    • 反射是作用在运行时的技术,此时已经不存在泛型了

反射的作用- 通验框架的底层原理

总结
  1. 反射的作用

    • 可以在运行时得到一个类的全部成分然后操作。
    • 可以破坏封装性。(很突出)
    • 可以破环泛型约束性。(很突出)
    • 更重要的用途适合做Java高级框架
package com.yu.Day1013Demo.framework;

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;
}
}
package com.yu.Day1013Demo.framework;

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;
}
}
package com.yu.Day1013Demo.framework;

import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field; public class MybatisUtil {
/**
* 保存任意类型的对象
* @param obj
*/
public static void save(Object obj){ try (
PrintStream ps = new PrintStream(new FileOutputStream("src//datast.txt",true));
){
//1.提取这个第项的全部成员便,只有反射可以解决
Class c = obj.getClass();
// c.getSimpleName()获取当前类名 c.getName获取全限名 包名加类名
ps.println("========"+c.getSimpleName()+"==========="); //2. 提取全部成员变量
Field[] fields = c.getDeclaredFields();
//3.获取成员变量信息
for (Field field : fields) {
String name = field.getName();
//提取本成员变量在obj对象中的值(取值)
field.setAccessible(true);
String value = field.get(obj)+"";
ps.println(name+"="+value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.yu.Day1013Demo.framework;

public class ReflectDemo {
public static void main(String[] args) throws Exception{
Student s = new Student("yu",'男',18,"qlit","chi,wan");
MybatisUtil.save(s);
Teacher t = new Teacher("yu",'男',10010);
MybatisUtil.save(t); }
}

注解

概述

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

作用

  • 对Java中类、方法、成员变量做标记,然后进行特殊处理,至于到底做何种处理由业务需求来决定

自定义注解

格式
  • 自定义注解就是自己做一个注解来使用

  • public @interface 注解名称{
    public 属性类型 属性名() default 默认值;

    Java支持的数据类型基本上都支持

特殊属性
  • value属性,如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写
  • 但是如果有多个属性,且多个属性没有默认值,那么value名称不能省略的
package com.yu.Day1013Demo.d8_annotation;

public @interface Book {
String value();//可直接写value值
int age() default 99;
}

元注解

  • 就是注解注解的注解
元注解有两个
  • @Target:约束自定义注解只能在哪些地方使用
  • @Retention:申明注解的生命周期

@Target中可以使用的值定义在ElementType枚举类中,常用值如下

  • TYPE 类,接口
  • FIELD 成员变量
  • METHOD 成员方法
  • PARAMETER 方法参数
  • CONSTRUCTOR 构造器
  • LOCAL_VARIABLE 局部变量

@Retention中可以使用的值定义在RetentionPolicy枚举类中,常用值如下

  • SOURCE 注解只作用在源代码阶段,生成的字节码文件中不存在
  • CLASS 注解作用在源代码阶段,字节码文件阶段,运行阶段不存在,默认值
  • RUNTIME 注解作用在源代码阶段,字节码文件阶段,运行阶段(开发常用)

注解的解析

  • 注解的操作中进场需要进行解析,注解的注解就是判断是否存在注解,存在注解就解析出内容
与注解解析相关的接口
  • Annotation:注解的顶级接口,注解都是Annotation类型的对象
  • AnnotatedElement:该接口定义了与注解解析相关的解析方法
方法 说明
Annotation[] getDeclaredAnnotations() 获得当前对象上使用的所有注解,发货注解数组
T getDeclaredAnnotation(Class annotationClass) 根据注解类型获得对应注解对象
boolean isAnnotationPresent(Class annotationClass) 判断档期啊对象是否使用了指定的注解,如果使用了则返回true,否则返回false
  • 所有的类成分Class,Method,Field,Constructor,都实现了AnnotatedElement接口他们都拥有解析注解的能力
解析注解的技巧
  • 注解在哪个成分上,我们就先拿哪个成分对象
  • 比如注解作用在成员方法,则要获得该成员方法对应的Method对象,再来拿上面的注解
  • 比如注解作用在类上,则要该类的Class对象,再来拿上面的注解
  • 比如注解作用在成员变量上,则要获得该成员变量对应的Field对象,再来拿上面的注解
package com.yu.Day1013Demo.d8_annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface Bookk {
String value();
double price() default 100;
String[] authors(); }
package com.yu.Day1013Demo.d8_annotation;

import org.junit.Test;

import java.lang.reflect.Method;
import java.util.Arrays; public class AnnotationDemo02 {
@Test
public void parseClass(){
Class c = BookStore.class;
if(c.isAnnotationPresent(Bookk.class)){
Bookk book = (Bookk)c.getDeclaredAnnotation(Bookk.class);
System.out.println(book.value());
System.out.println(Arrays.toString(book.authors()));
System.out.println(book.price());
}
}
@Test
public void parseMethod() throws NoSuchMethodException {
Class c = BookStore.class;
Method m = c.getDeclaredMethod("test");
if(m.isAnnotationPresent(Bookk.class)){
Bookk book = (Bookk)m.getDeclaredAnnotation(Bookk.class);
System.out.println(book.value());
System.out.println(Arrays.toString(book.authors()));
System.out.println(book.price());
}
}
}
@Bookk(value = "情深深雨蒙蒙",price = 99.9,authors = {"琼瑶","dlei"})
class BookStore{
@Bookk(value = "三少爷的",authors = {"yu","2222"})
public void test(){}
}

注解的应用:JUnit

package com.yu.Day1013Demo.d8_annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface MyTest {
}
package com.yu.Day1013Demo.d8_annotation;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; public class AnnotationDemo03 {
@MyTest
public void test1(){
System.out.println("1111");
}
@MyTest
public void test2(){
System.out.println("2222");
}
public void test3(){
System.out.println("33333");
} public static void main(String[] args) throws Exception, IllegalAccessException {
AnnotationDemo03 t = new AnnotationDemo03();
Class c = AnnotationDemo03.class;
Method[] methods = c.getDeclaredMethods();
for (Method method : methods) {
if(method.isAnnotationPresent(MyTest.class)){
method.invoke(t);
}
}
}
}

动态代理

概述

代理主要是对对象的行为额外做一些辅助操作
如何创建代理对象
  • Java中代理的代表类是:java.lang.reflect.Proxy
  • Proxy提供了一个静态方法,用于为对象产生一个代理对象返回
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
//为对象返回一个代理对象
//参数一:定义代理类的类加载器
//参数二:代理类要实现的接口列表
//参数三:将方法调用分派到的处理程序。(代理对象的核心处理程序)
总结
  1. 代理是什么?

    • 一个对象,用来对被代理对象的行为额外做一些辅助工作
  2. 在Java中实现动态代理的步骤是什么样的?
    • 必须存在接口
    • 被代理对象需要实现接口
    • 使用Proxy类提供的方法,创建对象的代理对象
  3. 通过代理对象调用方法,执行流程是什么样的
    • 先走向代理
    • 代理可以为方法额外做一些辅助工作
    • 开发真正触发对象的方法的执行
    • 回到代理中,由代理负责返回结果给方法的调用者

动态代理的优点

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

接口

package com.yu.Day1013Demo.d9Demo;

public interface Skll {
void jump();
void sing();
}

对象

package com.yu.Day1013Demo.d9Demo;

public class Star implements Skll {
private String name;
public Star(String name){
this.name = name;
}
@Override
public void jump() {
System.out.println(name+"正在跳舞!!!");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} @Override
public void sing() { System.out.println(name+"正在唱歌!!!");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

测试类

package com.yu.Day1013Demo.d9Demo;

public class Demo01 {
public static void main(String[] args) {
Star s = new Star("");
// Skll s2 = StarAgentProxy.getProxy(s);
Skll s2 = SKLLLLL.getStart(s);
s2.jump();
s2.sing();
}
}

代理类

package com.yu.Day1013Demo.d9Demo;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class SKLLLLL {
public static <T> T getStart(T obj){
return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long StartTime = System.currentTimeMillis();
Object re = method.invoke(obj,args);
long endTimes = System.currentTimeMillis();
System.out.println("方法名称:"+method.getName()+"方法耗时:"+(endTimes-StartTime)/1000.0+"S");
return re;
}
});
} }

Javaheima20的更多相关文章

随机推荐

  1. eNSP报错41解决方法

    1.点击右上角的菜单 2.工具>>注册设备,全部勾选,然后注册,就行了.

  2. 强烈推荐的elasticsearch集群连接工具: elasticvue

    个人感觉非常棒的es-cluster连接工具, 检查状态什么的, 一目了然, 支持中文超方便, 比elasticSearchHead好用多了. 安装方法打开微软浏览器edge-商城搜索-Elastic ...

  3. 《Spring Boot从零开始学(视频教学版)》快速入门Spring Boot应用开发

    #好书推荐##好书奇遇季#<Spring Boot从零开始学(视频教学版)>,目前为止较好的一本Spring Boot入门书.京东当当天猫都有发售.本书配套示例代码.课件与教学视频.定价7 ...

  4. SQL自动生成表结构Excel说明文档

    针对已经存在表结构,快速生成整理表结构文档. SELECT字段中文名 = isnull(G.[value],''),字段名 = A.name,类型 = B.name,标识 = Case When CO ...

  5. maven 通用pom.xml

    1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http:// ...

  6. 设置Redhat终端显示中文

    修改.bash_profile,增加: export LC_ALL= export LANG=C source .bash_profile

  7. dvwa sql盲注教程

    原文地址:https://www.jianshu.com/p/757626cec742 一.DVWA-SQL Injection(Blind)测试分析 SQL盲注 VS 普通SQL注入: 普通SQL注 ...

  8. vulnhub:My_Tomcat_Host靶机

    kali:192.168.111.111 靶机:192.168.111.171 信息收集 端口扫描 nmap -A -v -sV -T5 -p- --script=http-enum 192.168. ...

  9. Oracle ASM磁盘组的常用操作

    1.查看现有磁盘组信息 select group_number gno,name,state,type,total_mb,free_mb,required_mirror_free_mb rmfmb,u ...

  10. pymongo解决查询的时区相差8小时

    背景 最近需要到mongoDB中查询数据,但是发现返回的日期总是和实际时间差8小时.到数据库查询了一下看到时间的确是准确的,只是查询出来的比实际的少了8小时. 通过网上查找资料了解到默认时区是UTC, ...