一、动态代理
Java 动态代理 是 Java 反射机制 的一种应用,主要用于 AOP(面向切面编程)、日志记录、权限控制、事务管理 等场景。
什么是 Java 代理?
代理是一种设计模式,它可以在不改变原始对象的情况下,增强或修改对象的行为。Java 代理有两种:
- 静态代理(编译时生成代理类)
- 动态代理(运行时动态创建代理类)
动态代理特点:无侵入式地给代码增加额外的功能
调用者 ==> 代理 ==> 对象
程序为什么需要代理?代理长什么样?
对象如果嫌身上干的事太多的话,开源通过代理来转移部分职责。
代理里面就是对象要被代理的方法。
java通过什么来保证代理的样子?
通过接口保证,后面的对象和代理需要实现同一个接口。接口中就是被代理的所有方法。
如何为Java对象创建一个代理对象?
- java.lang.reflect.Proxy类:提供了为对象产生代理对象的方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interface, 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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| 大明星类 package com.ryan.mydynamicproxy;
public class BigStar implements Star { private String name;
public BigStar() { }
public BigStar(String name) { this.name = name; }
@Override public String sing(String name) { System.out.println(this.name + "正在唱" + name); return "谢谢"; } @Override public void dance() { System.out.println(this.name + "正在跳舞"); }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@Override public String toString() { return "BigStar{" + "name='" + name + '\'' + '}'; } }
创建代理 package com.ryan.mydynamicproxy;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
public class ProxyUtil {
public static Star creatProxy(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.getName())) { System.out.println("准备话筒,收钱"); } else if ("dance".equals(method.getName())) { System.out.println("准备场地,收钱"); } return method.invoke(bigStar, args); } } ); return star; } }
需要代理的方法 package com.ryan.mydynamicproxy;
public interface Star { public String sing(String name); public void dance(); }
测试类 package com.ryan.mydynamicproxy;
public class Test { public static void main(String[] args) {
BigStar bigStar = new BigStar("鸡哥"); Star proxy = ProxyUtil.creatProxy(bigStar); String result = proxy.sing("只因你太美"); System.out.println(result); proxy.dance(); } }
|
二、反射
Java 反射(Reflection)是 Java 语言提供的一种机制,它允许程序在运行时动态地获取类的信息、创建对象、访问成员变量和调用方法,即使在编译时类型未知。这种能力主要依赖于 java.lang.reflect 包中的类,如 Class、Field、Method 和 Constructor。
反射的基本概念
Java 反射允许程序在运行时:
- 获取类的完整信息(类名、构造方法、字段、方法等)。
- 实例化对象(即使没有直接使用
new 关键字)。
- 调用私有和公共方法。
- 访问和修改私有字段。
反射示例图

1. 获取class对象的三种方式
- 方式一:
Class.forName("全类名");
全类名 = 包名 + 类名
- 方式二:
类名.class
- 方式三:
对象.getClass();
源代码阶段(Java文件、class文件):使用方式一(最为常用)
加载阶段(加载到内存时):使用方式二(一般更多的是当作参数使用)
运行阶段(在内存中创建类对象时:A a = new A(); :使用方式三(当已经有了这个类的对象时,才可以使用)
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
| package com.ryan.reflect;
public class ReflectDemo1 { public static void main(String[] args) throws ClassNotFoundException { Class clazz1 = Class.forName("com.ryan.reflect.Student");
Class clazz2 = Student.class;
Student stu = new Student(); Class clazz3 = stu.getClass();
System.out.println(clazz1 == clazz2); System.out.println(clazz2 == clazz3); } }
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 + '}'; } }
|
2. 利用反射获取构造方法

3. 利用反射获取成员变量

4. 利用反射获取成员方法
