目录
[Java 的静态代理与动态代理](#Java 的静态代理与动态代理)
[一. 静态代理](#一. 静态代理)
[1. 概念](#1. 概念)
[2. 实现](#2. 实现)
[(1) 定义目标接口](#(1) 定义目标接口)
[(2) 定义目标类](#(2) 定义目标类)
[(3) 定义代理类](#(3) 定义代理类)
[(4) 使用代理类](#(4) 使用代理类)
[二. 动态代理](#二. 动态代理)
[1. 概念](#1. 概念)
[2. JDK 动态代理](#2. JDK 动态代理)
[(1) 定义接口](#(1) 定义接口)
[(2) 接口的实现类](#(2) 接口的实现类)
[(3) 生成代理对象](#(3) 生成代理对象)
[(4) 使用代理类](#(4) 使用代理类)
[3. CGLIB 动态代理](#3. CGLIB 动态代理)
[(1) 添加 CGLIB 依赖](#(1) 添加 CGLIB 依赖)
[(2) 定义目标类 (无需实现接口)](#(2) 定义目标类 (无需实现接口))
[(3) 实现 MethodInterceptor 接口](#(3) 实现 MethodInterceptor 接口)
[(4) 使用代理类](#(4) 使用代理类)
Java 的静态代理与动态代理
一. 静态代理
1. 概念
静态代理是代理模式中++最基础++的实现方式.
静态代理要求 代理类在编译期就已确定 . 并且 代理类与目标类 实现相同的接口 或 继承相同父类. 通过静态代理, 我们可以在不修改目标类代码的情况下, 对其方法进行增强 (添加 日志, 权限校验 等功能).
静态代理的核心是:
-
定义一个目标接口, 包含需要被代理的方法.
-
目标类实现该接口, 提供具体的业务逻辑.
-
代理类也实现该接口, 内部持有目标对象的引用, 在调用目标方法前后添加增强逻辑.
外界通过调用代理类的方法, 间接调用目标类的方法, 从而实现功能增强.
2. 实现
(1) 定义目标接口
/**
* IAnimal 接口
* (这里写要被代理的方法)
*/
public interface IAnimal {
/**
* 吃饭
*/
public abstract void eat();
/**
* 睡觉
*/
public abstract void sleep();
}
(2) 定义目标类
/**
* 目标类 Animal
*/
public class Animal implements IAnimal{
@Override
public void eat() {
System.out.println("吃吃吃");
}
@Override
public void sleep() {
System.out.println("睡睡睡");
}
}
(3) 定义代理类
/**
* 代理类 AnimalProxy
*/
public class AnimalProxy implements IAnimal {
private final Animal animal;
public AnimalProxy(Animal animal) {
this.animal = animal;
}
@Override
public void eat() {
// 前置处理
System.out.println("饲养员准备食物");
animal.eat();
// 后置处理
System.out.println("饲养员收拾剩余食物");
}
@Override
public void sleep() {
// 前置处理
System.out.println("饲养员准备草席");
animal.sleep();
// 后置处理
System.out.println("饲养员叫醒小动物");
}
}
(4) 使用代理类
public class Test {
public static void main(String[] args) {
// 1.创建目标对象
Animal animal = new Animal();
// 2.创建代理对象(传入目标对象)
AnimalProxy proxy = new AnimalProxy(animal);
// 3.通过代理对象调用方法
proxy.eat();
System.out.println();
proxy.sleep();
}
}
运行结果:

二. 动态代理
1. 概念
动态代理是一种 在运行时动态创建代理对象 的机制. 这种机制允许我们在不修改原始类代码的情况下, 对目标类的方法进行增强 (如添加日志, 事务控制, 权限校验等).
这种机制是代理模式的高级实现, 相比静态代理 (在编译期生成代理类), 动态代理更加灵活, 能避免大量重复代码.
例如: 如果我们要正在项目中添加一些新的功能. 但是在成熟的项目中, 不建议进行 "侵入式修改" (修改原本已经能正常运行的代码). 所以此时我们就要选择动态代理, 它能够无侵入式地给代码增加额外功能.

2. JDK 动态代理
基于接口的代理.
实现步骤:
(1) 定义接口
定义一个接口, 该接口里是要代理的方法.
/**
* IAnimal 接口
* (这里写要被代理的方法)
*/
public interface IAnimal {
/**
* 吃饭
*/
public abstract void eat();
/**
* 睡觉
*/
public abstract void sleep();
}
(2) 接口的实现类
BigStar 类 实现 Star 接口 (要被代理的对象类)
public class Animal implements IAnimal{
@Override
public void eat() {
System.out.println("吃吃吃");
}
@Override
public void sleep() {
System.out.println("睡睡睡");
}
}
(3) 生成代理对象
ProxyUtil 生成代理对象
java.lang.reflect.Proxy 类: 提供了为对象生成代理对象的方法.
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
-
参数一: 用于 指定用哪个类加载器 去加载生成的代理类.
-
参数二: 指定接口数组. 这些接口用于指定要代理哪些方法.
-
参数三: 用来指定生成的代理对象要干什么事情.
ProxyUtil 类:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 代理工具类 ProxyUtil
* 作用: 为对象创建代理
*/
public class ProxyUtil {
/**
* 给Animal对象创建代理
* @param animal 被代理的明星对象
* @return 代理对象
*/
public static IAnimal createProxy(Animal animal) {
return (IAnimal) Proxy.newProxyInstance(
ProxyUtil.class.getClassLoader(), // 参数一: 用于指定用哪个类加载器去加载生成的代理类
new Class[]{IAnimal.class}, // 参数二: 用于指定代理对象要实现哪些接口
new InvocationHandler() { // 参数三: 用于指定代理对象要干什么事情
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/*
参数1: 要代理的对象
参数2: 要运行的方法
参数3: 方法的参数
*/
// 前置处理
if (("eat").equals(method.getName())) {
System.out.println("饲养员准备食物");
} else if ("sleep".equals(method.getName())) {
System.out.println("饲养员准备草席");
}
// 调用目标类的原始方法 (通过代理调用父类方法)
Object result = (method.invoke(animal, args));
// 后置处理
if (("eat").equals(method.getName())) {
System.out.println("饲养员收拾剩余食物");
} else if ("sleep".equals(method.getName())) {
System.out.println("饲养员叫醒小动物");
}
return result;
}
});
}
}
(4) 使用代理类
Test 测试类:
public class Test {
public static void main(String[] args) {
Animal animal = new Animal();
// 1.获取代理对象
IAnimal proxy = ProxyUtil.createProxy(animal);
// 2.调用代理对象的方法
proxy.eat();
System.out.println();
proxy.sleep();
}
}
运行结果:

3. CGLIB 动态代理
基于类的代理.
实现步骤:
(1) 添加 CGLIB 依赖
在 pom.xml 文件中添加如下依赖:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
(2) 定义目标类 (无需实现接口)
public class Animal {
public void eat() {
System.out.println("吃吃吃");
}
public void sleep() {
System.out.println("睡睡睡");
}
}
(3) 实现 MethodInterceptor 接口
(定义增强逻辑)
CGLIB 的核心是 MethodInterceptor 接口, 其 intercept() 方法类似于 JDK 的 invoke. 在代理方法被调用时执行, 参数包括:
-
obj: 代理对象 (子类实例)
-
method: 被调用的目标方法 (反射对象)
-
args: 方法参数
-
proxy: 方法代理对象 (用于调用父类的原始方法)
public class AnimalInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 前置处理
if (("eat").equals(method.getName())) {
System.out.println("饲养员准备食物");
} else if ("sleep".equals(method.getName())) {
System.out.println("饲养员准备草席");
}
// 调用目标类的原始方法 (通过代理调用父类方法)
Object result = proxy.invokeSuper(obj, args);
// 后置处理
if (("eat").equals(method.getName())) {
System.out.println("饲养员收拾剩余食物");
} else if ("sleep".equals(method.getName())) {
System.out.println("饲养员叫醒小动物");
}
return result;
}
}
(4) 使用代理类
import net.sf.cglib.proxy.Enhancer;
public class Test {
public static void main(String[] args) {
// 1. 创建目标对象
Animal animal = new Animal();
// 2. 创建 Enhancer (CGLIB的代理生成器)
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Animal.class); // 设置父类 (目标类)
enhancer.setCallback(new AnimalInterceptor()); // 设置增强处理器
// 3. 生成代理对象 (是Animal的子类)
Animal proxy = (Animal) enhancer.create();
// 4. 调用代理对象的方法
proxy.eat();
System.out.println();
proxy.sleep();
}
}
运行结果:
