反射
package Basic.src.com.reflect;import org.junit.Test;import java.lang.reflect.Method;public class Test4Method {@Testpublic void testGetMethhod() throws Exception {//1.反射第一步:先得到Class对象Class cat = Cat.class;//2.获取类的全部成员方法Method[] methods = cat.getDeclaredMethods();//3.遍历这个数组中的每个方法对象for (Method method : methods) {System.out.println(method.getName()+"------------"+method.getParameterCount()+"------------"+method.getReturnType());}//4.获取某个方法对象Method run = cat.getDeclaredMethod("run");//拿run(),无参的System.out.println(run.getName()+"------------"+run.getParameterCount()+"------------"+run.getReturnType());Cat cat1 = new Cat();run.setAccessible(true);//暴力反射public void run()即使是private也可以访问Object rs = run.invoke(cat1);//调用方法System.out.println(rs);//nullSystem.out.println("====================================");Method eat = cat.getDeclaredMethod("eat", String.class);System.out.println(eat.getName()+"------------"+eat.getParameterCount()+"------------"+eat.getReturnType());eat.setAccessible(true);//private String eat(String name)String es = (String)eat.invoke(cat1,"鱼");System.out.println(es);//耄耄最爱食:鱼System.out.println(eat);//private java.lang.String Basic.src.com.reflect.Cat.eat(java.lang.String)}
}
package Basic.src.com.reflect;import org.junit.Test;public class Test5Frame {@Testpublic void save() throws Exception {Student s1 = new Student("哈基滨", 22, '公', 185.3, "唱跳rap");Teacher t1 = new Teacher("南北绿豆", 999.9);//需求:把任意对象的字段名称和其对应的值等信息,保存到文件中去ObjectFrame.saveObject(s1);ObjectFrame.saveObject(t1);}
}
package Basic.src.com.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("Basic\\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)+"";//+""转为String类型ps.println(name+"="+value);}ps.close();}
}
注解
注解本质上接口,继承了annotation
package Basic.src.com.annotation;@MyTest1(aaa="牛魔王",ccc={"HTML","JAVA"})
@MyTest2("孙悟空")//当只有一个未默认化的属性并且叫value,那么value可以省略
public class AnnotationTest1 {@MyTest1(aaa="铁山公主",bbb=false,ccc={"Python","前端","Java"})public void test1(){System.out.println("test1");}public static void main(String[] args) {//执行后会把上面的注解从java文件编译为class后缀的文件//"C:\Users\Lenovo\Desktop\note\code\JavaSE\out\production\JavaSE\Basic\src\com\annotation\MyTest1.class"}
}
package Basic.src.com.annotation;/*** 自定义注解*/public @interface MyTest1 {String aaa();boolean bbb() default true;String[] ccc();
}
package Basic.src.com.annotation;public @interface MyTest2 {String value();//特殊属性int age() default 0;
}
元注解
指的是:修饰注解的注解
@Target @Retention
package Basic.src.com.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 MyTest3 {
}
package Basic.src.com.annotation;/** 元注解* */
@MyTest3
public class AnnotationTest2 {//@MyTest3报错,这个是成员变量private String name;@MyTest3//不报错,这个是方法public void test(){}
}
package Basic.src.com.annotation;import org.junit.Test;import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;public class AnnotationTest3 {@Testpublic void parseClass() {//1.先得到class类对象Class<Demo> c = Demo.class;//2.解析上面的注解//判断这个类上面是不是包含了某个注解if(c.isAnnotationPresent(MyTest4.class)){//MyTest4.class)是填进去的注解类型MyTest4 myTest4 =c.getDeclaredAnnotation(MyTest4.class);//就是Demo类里面有没有MyTest4这个注解System.out.println(myTest4.value());System.out.println(myTest4.aaa());System.out.println(Arrays.toString(myTest4.bbb()));}Annotation[] da = c.getDeclaredAnnotations();for (Annotation annotation : da) {}}@Testpublic void parseMethod() throws Exception {//1.先得到class类对象Class<Demo> c = Demo.class;Method m = c.getDeclaredMethod("test1");//2.解析上面的注解//判断这个"test1"测试方法对象上面是不是包含了某个注解if(m.isAnnotationPresent(MyTest4.class)){//MyTest4.class)是填进去的注解类型MyTest4 myTest4 =c.getDeclaredAnnotation(MyTest4.class);//就是Demo类里面有没有MyTest4这个注解System.out.println(myTest4.value());System.out.println(myTest4.aaa());System.out.println(Arrays.toString(myTest4.bbb()));}}
}
package Basic.src.com.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest4 {String value();double aaa() default 100;String[] bbb();
}
package Basic.src.com.annotation;
@MyTest4(value="蜘蛛精",aaa=99.5,bbb={"至尊宝","黑马"})
public class Demo {@MyTest4(value="哈基滨",aaa=66.6,bbb={"叮咚鸡","大狗嚼嚼嚼"})public void test1(){System.out.println("test1");}
}
package Basic.src.com.annotation;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;/*** 目标:模拟Junit框架的设计*/public class AnnotationTest4 {//@MyTestpublic void test1(){System.out.println("test1");}@MyTestpublic void test2(){System.out.println("test2");}public void test3(){System.out.println("test3");}@MyTestpublic void test4(){System.out.println("test4");}public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {AnnotationTest4 a = new AnnotationTest4();//实现启动程序//1.得到class对象Class<AnnotationTest4> c = AnnotationTest4.class;//2.提取这个类中的全部成员方法Method[] Methods = c.getDeclaredMethods();//3.遍历这个数组中的每个方法,看方法是是否存在//触发该方法的执行for (Method method : Methods) {if(method.isAnnotationPresent(MyTest.class)){//说明当前方法上存在该注解,触发该方法执行method.setAccessible(true);method.invoke(a);// Method.invoke() 方法时,括号中第一个参数需要传入的是调用该方法的对象实例(即方法所属的对象),其作用是指定 “在哪个对象上执行当前方法”。}}}
}
package Basic.src.com.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 Basic.src.com.annotation.Proxy;public class BigStar implements Star {// implements Star是生成代理的约定{private String name;public BigStar(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String sing(String name) {System.out.println(this.name + "正在唱:" + name);return "thank you!";}public void dance(){System.out.println(this.name+"正在唱跳rap");}
}
package Basic.src.com.annotation.Proxy;public interface Star {//先声明哪些方法要被代理String sing(String name);void dance();
}
package Basic.src.com.annotation.Proxy;public class BigStar implements Star {// implements Star是生成代理的约定{private String name;public BigStar(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String sing(String name) {System.out.println(this.name + "正在唱:" + name);return "thank you!";}public void dance(){System.out.println(this.name+"正在唱跳rap");}
}
package Basic.src.com.annotation.Proxy;public interface Star {//先声明哪些方法要被代理String sing(String name);void dance();
}
package Basic.src.com.annotation.Proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class ProxyUtil {public static Star createProxy(BigStar bigStar){Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),new Class[]{Star.class}, new InvocationHandler() {//创建一个实现了 Star 接口的动态代理对象 starProxy//ProxyUtil 是你自己编写的类(位于 Basic.src.com.annotation.Proxy 包下),它的类加载器是 应用类加载器(AppClassLoader),负责加载用户编写的类(包括你的 Star 接口、BigStar 类等)。//因此,ProxyUtil 的类加载器与 Star 接口的类加载器是同一个(或存在父子关系,符合双亲委派模型),它们属于同一个 “命名空间”。@Override //回调方法public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//我们的代理对象要做的事情//Object proxy 代理对象本身:starProxy 对象本身//Method method 调用的什么函数,比如sing dance//Object[] args 存储了客户端调用代理对象方法时传入的实际参数值,调用的比如sing方法里面的参数if(method.getName().equals("sing")){System.out.println("准备话筒,收钱");//return method.invoke(bigStar,args);//args指的可能是唱哪首歌对应的参数}else if(method.getName().equals("dance")){System.out.println("准备场地,收钱");//return method.invoke(bigStar,args);}else {//return method.invoke(bigStar,args);}return method.invoke(bigStar,args);//调用BigStar里面的该method对应的方法}});//创建代理Proxy.newProxyInstance/** ClassLoader loader,指定一个类加载器,生成一个代理类(固定)Class<?>[] interfaces,指定生成的代理长什么样,有什么方法,接收多个数组(接口数组里面的方法就可以被接收)InvocationHandler h指定生成的代理对象要干什么事情,代理干什么事情是由这个决定的* */return starProxy;}
}
package Basic.src.com.annotation.Proxy;public class TestStar {public static void main(String[] args) {BigStar s = new BigStar("杨超越");Star starProxy = ProxyUtil.createProxy(s);//ProxyUtil类是我们自己编写的,里面有createProxy方法//创建代理对象,把s传进去,这个工具类就为杨超越类创建了一个代理对象String rs = starProxy.sing("好日子");//这里的sing方法会调用代理ProxyUtil类中的invoke方法,这里是接口回调System.out.println(rs);starProxy.dance();}
}
改造
package Basic.src.com.annotation.Proxy.Exercise;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class ProxyUtil {//代理对应规则public static UserService createUserService(UserService userService){UserService userServiceProxy = (UserService) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), new Class[]{UserService.class},new InvocationHandler() {@Overridepublic 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)+"ms");return rs;}else{Object rs = method.invoke(userService, args);return rs;}}});return userServiceProxy;}
}
package Basic.src.com.annotation.Proxy.Exercise;public interface UserService {//登录功能void login(String name,String password)throws Exception;//删除用户void deleteUsers()throws Exception;//查询用户,返回数组的形式String[] selectUsers()throws Exception;
}
package Basic.src.com.annotation.Proxy.Exercise;public class UserServiceimpl implements UserService {@Overridepublic void login(String name, String password) throws Exception {if("admin".equals(name) && "123456".equals(password)){System.out.println("登录成功,欢迎光临本系统");}else{System.out.println("登录失败,用户名或密码错误");}Thread.sleep(1000);}@Overridepublic void deleteUsers() throws Exception {System.out.println("成功删除了一万个用户");Thread.sleep(1500);}@Overridepublic String[] selectUsers() throws Exception {System.out.println("查询出了三个用户");String[] names = {"张三","李四","王五"};Thread.sleep(500);return names;}
}
package Basic.src.com.annotation.Proxy.Exercise;import java.lang.reflect.Proxy;
import java.util.Arrays;public class Test {public static void main(String[] args) throws Exception {//1.创建用户业务对象//UserService userService = new UserServiceimpl();//接口是 “类” 的一种特殊形式,这个没有计时功能UserService userService = ProxyUtil.createUserService(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("===========================");}
}