文章来自我的个人笔记,可以移步到 -> 创造者MC的个人笔记 继续浏览
前言
在使用 SpingAOP 时接触到了代理,觉得非常神奇,明明没有在目标类中添加代码,却能在方法执行前后编写额外代码。
多数文章没有把代理真正讲明白,我看了一些文章后进行了汇总,明白了代理的本质。
图解代理模式

静态代理和动态代理的区别和联系
区别
静态代理:自己写代理类,自己创建代理类的对象。
动态代理:利用 ASM 动态生成代理类并创建代理类的对象。
联系
静态代理和动态代理的原理都是组合或继承!
JDK 动态代理使用组合方式实现。
CGLIB 动态代理使用继承方式实现。
测试代码
把图中的测试代码贴到下方,大家可以自己去尝试。
静态代理
继承
class Eat {
public void eat() {
System.out.println("吃饭");
}
}
public class EatProxy extends Eat {
@Override
public void eat() {
System.out.println("饭前");
super.eat();
System.out.println("饭后");
}
public static void main(String[] args) {
// 这里的类型与图里的不一样,改成父类了,大家可以好好感受一下多态。
Eat eatProxy = new EatProxy();
eatProxy.eat();
}
}
组合
interface Fly {
void fly();
}
class Bird implements Fly {
@Override
public void fly() {
System.out.println("鸟在飞");
}
}
class Plane implements Fly {
@Override
public void fly() {
System.out.println("飞机在飞");
}
}
public class FlyProxy implements Fly{
private Fly fly;
public FlyProxy(Fly fly) {
this.fly = fly;
}
@Override
public void fly() {
System.out.println("飞之前");
fly.fly();
System.out.println("飞之后");
}
}
class Test {
public static void main(String[] args) {
Fly fly = new FlyProxy(new Bird());
fly.fly();
fly = new FlyProxy(new Plane());
fly.fly();
}
}
动态代理
JDK 动态代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Work {
void work();
}
class JavaEngineer implements Work {
@Override
public void work() {
System.out.println("IDEA 启动!");
}
}
class WorkProxy implements InvocationHandler {
private Work work;
public WorkProxy(Work work) {
this.work = work;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法:" + method.getName() + "() 执行前");
Object invoke = method.invoke(work, args);
System.out.println("方法:" + method.getName() + "() 执行后");
return invoke;
}
}
public class JDKProxy {
public static void main(String[] args) {
// 把下方注释掉的代码去掉注释,可以在执行后得到生成类的 .class 文件,用 IDEA 打开即可通过 IDEA 的反编译查看生成的具体类的内容(JDK 1.8)。
// System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
JavaEngineer javaEngineer = new JavaEngineer();
/*
参数一: 被代理类的 CLass 对象
参数二:接口类的 Class 对象。被代理对象所实现的接口
参数三:调用处理器。被调用对象的那个方法被调用后该如何处理
*/
Work work = (Work) Proxy.newProxyInstance(JavaEngineer.class.getClassLoader(), new Class[]{Work.class}, new WorkProxy(javaEngineer));
work.work();
}
}
CGLIB 动态代理
注意:需要先引入依赖!
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
class MinecraftPlayer {
public void play() {
System.out.println("玩 Minecraft");
}
}
class PlayerProxy implements MethodInterceptor {
// 代理对象
private Object object;
public PlayerProxy(Object target) {
// 创建加强器,用来创建动态代理类
Enhancer enhancer = new Enhancer();
// 为加强器指定要代理的业务类(为下面要生成的代理类指定父类)
enhancer.setSuperclass(target.getClass());
// 设置回调对象,对于代理类上的所有的方法调用,都会调用 CallBack,而 CallBack 需要实现 intercept 方法进行拦截
enhancer.setCallback(this);
// 创建动态代理类的对象
object = enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("方法:" + method.getName() + "() 执行之前");
Object result = methodProxy.invokeSuper(o, objects);
System.out.println("方法:" + method.getName() + "() 执行之后");
return result;
}
public Object getObject() {
return object;
}
}
public class CGLIBProxy {
public static void main(String[] args) {
PlayerProxy playerProxy = new PlayerProxy(new MinecraftPlayer());
MinecraftPlayer minecraftPlayer = (MinecraftPlayer) playerProxy.getObject();
minecraftPlayer.play();
}
}