该笔记基于B站视频编写
1. 动态代理的思想分析
程序为什么需要代理?
代理在程序设计中有很重要的作用,它可以帮助我们更好地管理和扩展代码,同时也能提高代码的安全性和隐私性
使用代理的好处:
- 降低程序复杂度
- 易于业务扩展
- 代码高内聚低耦合
- 增强功能
- 增强安全性和隐私性
代理就像中介公司一样,它通过接口来自动要代理那些方法
代理和被代理的类要实现同一个接口
代码实现
定义一个接口(Star),里面放需要被代理的方法
1 2 3 4 5 6 7 8 9 10 11 12
|
public interface Star { abstract String sing(String name); abstract void dance(String name); }
|
创建一个需要被代理的类(BigStar),实现接口Star
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class BigStar implements Star{ private String name;
public BigStar() { }
@Override public String sing(String name) { System.out.println(this.name + "正在唱" + name); return "谢谢"; }
@Override public void dance(String name) { System.out.println(this.name + "正在跳舞" + name); }
public BigStar(String name) { this.name = name; }
public String getName() { return name; }
public void setName(String name) { this.name = name; } }
|
创建代理对象
java.lang.reflect.Proxy类:提供了为对象产生代理对象的方法
1
| public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
|
- 参数一:用于指定用哪个类加载器,去加载生成的代理类
- 参数二:指定接口,这些接口用于指定生成的代理会有哪些方法,以集合的形式添加
- 参数三:用来指定生成的代理对象要干什么事情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
public class ProxyUtil {
public static Star crateProxy(BigStar bigStar) { Star star = (Star) Proxy.newProxyInstance( ProxyUtil.class.getClassLoader(), new Class[]{Star.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("sing".equals(method)) { System.out.println("准备话筒"); } else if ("dance".equals(method)) { System.out.println("准备场地"); } return method.invoke(bigStar,args); } } ); return star; }
}
|
编写测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
public class Test { public static void main(String[] args) { BigStar bigStar = new BigStar("鸡哥"); Star proxy = ProxyUtil.crateProxy(bigStar); String result = proxy.sing("只因你太美"); System.out.println(result); } }
|
运行结果
2. 反射的概述
反射允许对封装类的字段,方法和构造函数的信息进行编程访问
Java 反射,就是在运行状态中
- 获取任意类的名称、package信息、所有属性、方法、注解、类型、类加载器等
- 获取任意对象的属性,并且能改变对象的属性
- 调用任意对象的方法
- 判断任意一个对象所属的类
- 实例化任意一个类的对象
3. 获取class对象
- Class.forName(“全类名”)
- 类名.class
- 对象.getClass()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package com.zheng.myreflect;
public class Student { private String name; private int age;
public Student() { }
public Student(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 "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public class MyReflectDemo { public static void main(String[] args) throws ClassNotFoundException {
Class clazz1 = Class.forName("com.zheng.myreflect.Student");
Class clazz2 = Student.class;
Student stu = new Student(); Class clazz3 = stu.getClass();
System.out.println(clazz1); System.out.println(clazz1==clazz2); System.out.println(clazz2==clazz3); } }
|

4. 反射获取构造方式
Class类中用于获取构造方法的方法
- Constructor<?>[]getConstructors():返回所有公共构造方法对象的数组
- Constructor<?>[]getDeclaredConstructors():返回所有构造方法对象的数组
- ConstructorgetConstructor(Class<?>…parameterTypes):返回单个公共构造方法对象
- ConstructorgetDeclaredConstructor(Class<?>…parameterTypes):返回单个构造方法对象
Constructor类中用于创建对象的方法
- T newInstance(Object… initargs):根据指定的构造方法创建对象
- setAccessible(boolean flag):设置为true,表示取消访问检查
JAVA反射机制中,getModifiers()方法返回int类型值表示该字段的修饰符
| 修饰符 |
对应的int类型 |
| public |
1 |
| private |
2 |
| protected |
4 |
| static |
8 |
| final |
16 |
| synchronized |
32 |
| volatile |
64 |
| transient |
128 |
| native |
256 |
| interface |
512 |
| abstract |
1024 |
| strict |
2048 |
定义一个学生类,定义4个构造方法,其中两个公共的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| public class Student {
private String name; private int age;
public Student() { }
public Student(String name) { this.name = name; }
protected Student(int age) { this.age = age; }
private Student(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 "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
|
定义测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Parameter;
public class MyReflectDemo {
public static void main(String[] args) throws Exception { Class clazz = Class.forName("com.zheng.myrelfect2.Student");
Constructor[] cons1 = clazz.getConstructors(); for (Constructor con : cons1) { System.out.println(con); } System.out.println("****************************");
Constructor[] cons2 = clazz.getDeclaredConstructors(); for (Constructor con : cons2) { System.out.println(con); } System.out.println("****************************");
Constructor con1 = clazz.getConstructor(); System.out.println(con1); System.out.println("****************************");
Constructor con2 = clazz.getConstructor(String.class); System.out.println(con2); System.out.println("****************************");
Constructor con3 = clazz.getDeclaredConstructor(String.class, int.class); System.out.println(con3); System.out.println("分割线******************************************************************");
int modifiers = con3.getModifiers(); System.out.println(modifiers); System.out.println("****************************");
Parameter[] parameters = con3.getParameters(); for (Parameter parameter : parameters) { System.out.println(parameter); } System.out.println("****************************");
con3.setAccessible(true); Student stu = (Student) con3.newInstance("正哥", 18); System.out.println(stu);
} }
|
运行结果
5. 反射获取成员变量
Class类中用于获取成员变量的方式
- Field[] getFields():返回所有公共成员变量对象的数组
- Field[] getDeclaredFields():返回所有成员变量对象的数组
- Field[] getField(String name):返回单个公共成员变量对象
- Field getDeclaredField(String name):返回单个成员变量对象
Field类中用于创建对象的方法
- void set(Object obj, Object value):赋值
- Object get(Object obj):获取值
创建一个学生类,定义三个成员变量,一个公共的,两个私有的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| public class Student { private String name; private int age; public String gender;
public Student() { }
public Student(String name, int age, String gender) { this.name = name; this.age = age; this.gender = gender; }
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 String getGender() { return gender; }
@Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", gender='" + gender + '\'' + '}'; }
public void setGender(String gender) { this.gender = gender; } }
|
定义测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| import java.lang.reflect.Field;
public class MyReflectDemo { public static void main(String[] args) throws Exception{
Class clazz = Class.forName("com.zheng.myrelflect3.Student");
Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { System.out.println(field); } System.out.println("*****************************");
Field name = clazz.getDeclaredField("name"); System.out.println(name); System.out.println("*****************************");
int modifiers = name.getModifiers(); System.out.println(modifiers); System.out.println("*****************************");
String n = name.getName(); System.out.println(n); System.out.println("*****************************");
Class<?> type = name.getType(); System.out.println(type); System.out.println("*****************************");
Student stu = new Student("正哥", 18, "男"); name.setAccessible(true); String nameValue = (String) name.get(stu); System.out.println(nameValue); System.out.println("*****************************");
name.set(stu, "正哥学Java"); System.out.println(stu); } }
|
测试结果
6. 反射获取成员方法
Class类中用于获取成员方法的方法
- Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的(包含父类的)
- Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
- Method[] getMethod(String name, Class<?>…parameterTypes):返回单个公共成员方法对象
- Method[] getDeclaredMethod(String name, Class<?>…paramenterTypes):返回单个成员方法对象
Method类中用于创建对象的方法
Object invoke(Object obj, Object…args):运行方法
- 参数一:用obj对象调用该方法
- 参数二:调用方法的传递的参数(没有就不用写)
- 返回值:方法的返回值(没有就不用写)
定义一个student类,有两个成员方法,一个是公共方法sleep(),一个是私有方法eat()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| package com.zheng.myrelflect4;
import java.io.IOException;
public class Student { private String name; private int age;
public Student() { }
public Student(String name, int age) { this.name = name; this.age = age; }
public String getName() { return name; }
public void sleep() { System.out.println("睡觉"); }
private String eat(String something) throws NullPointerException{ System.out.println("再吃" + something); return "太好吃了"; }
public void setName(String name) throws IOException { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; } }
|
定义一个测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| package com.zheng.myrelflect4;
import java.lang.reflect.Method; import java.lang.reflect.Parameter;
public class MyReflectDemo {
public static void main(String[] args) throws Exception{ Class<?> clazz = Class.forName("com.zheng.myrelflect4.Student");
Method[] methods = clazz.getMethods(); for (Method method : methods) { System.out.println(method); } System.out.println("分割线********************分割线");
Method[] declaredMethods = clazz.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod); } System.out.println("分割线********************分割线");
Method method = clazz.getDeclaredMethod("eat",String.class); System.out.println(method); System.out.println("*****************************");
int modifiers = method.getModifiers(); System.out.println(modifiers);
String name = method.getName(); System.out.println(name); System.out.println("*****************************");
Parameter[] parameters = method.getParameters(); for (Parameter parameter : parameters) { System.out.println(parameter); }
Class<?>[] exceptionTypes = method.getExceptionTypes(); for (Class<?> exceptionType : exceptionTypes) { System.out.println(exceptionType); } System.out.println("*****************************");
Student stu = new Student(); method.setAccessible(true); String result = (String) method.invoke(stu, "汉堡"); System.out.println(result); } }
|
测试结果
