代理模式
代理模式基本介绍
如果不使用代理模式,按照我们传统模式是Client直接调用TargetObject对象。
静态代理
思路分析图解
静态代理代码实现
package com.sky.proxy.staticproxy;
// 接口
public interface ITeacherDao {
void teach(); // 授课的方法
}
package com.sky.proxy.staticproxy;
/**
* 目标对象
*/
public class TeacherDao implements ITeacherDao {
@Override
public void teach() {
System.out.println(" 老师授课中 。。。。。");
}
}
package com.sky.proxy.staticproxy;
/**
* 代理对象
*/
public class TeacherDaoProxy implements ITeacherDao {
private ITeacherDao target; // 目标对象
// 通过创建构造器,进行目标对象的设置
public TeacherDaoProxy(ITeacherDao target) {
this.target = target;
}
@Override
public void teach() {
System.out.println(" 开始代理 。。。。。"); // 可以添加额外的功能
target.teach(); // 核心方法
System.out.println(" 提交 。。。。。"); // 可以添加额外的功能
}
}
package com.sky.proxy.staticproxy;
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
TeacherDaoProxy proxy = new TeacherDaoProxy(new TeacherDao()); // 代理对象 和 目标对象
proxy.teach();
}
}
开始代理 。。。。。
老师授课中 。。。。。
提交 。。。。。
****
静态代理的优缺点
动态代理
动态代理应用实例
代码实现
package com.sky.proxy.dynamicproxy;
/**
* 接口
*/
public interface ITeacherDao {
void teach(); // 授课方法
void sayHi(String name); //
}
package com.sky.proxy.dynamicproxy;
/**
* 目标对象
*/
public class TeacherDao implements ITeacherDao {
@Override
public void teach() {
System.out.println(" 老师授课中 。。。。 ");
}
@Override
public void sayHi(String name) {
System.out.println(" hello " + name);
}
}
package com.sky.proxy.dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 代理工厂
*/
public class ProxyFactory {
private Object target; // 聚合一个目标对象(也就是被代理的对象)
// 构造器,对target进行初始化
public ProxyFactory(Object target) {
this.target = target;
}
// 给目标对象生成一个代理对象
/**
* newProxyInstance(ClassLoader loader,
* Class<?>[] interfaces,
* InvocationHandler h)
* throws IllegalArgumentException
*
说明:
1.ClassLoader loader:指定当前目标对象使用的类加载器,获取加载器的方法 固定
2.Class<?>[] interfaces,目标对象实现的接口类型,使用泛型方法确认类型
3.InvocationHandler h:事件处理,执行目标对象的方法时,会触发事件处理器方法,会把
当前执行的目标对象方法作为参数传入。
* @return
*/
public Object getProxyInstance(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(" JDK代理开始。。。 ");
// 反射机制调用目标对象的方法
Object returnVal = method.invoke(target, args);
System.out.println(" JDK代理提交。。。 ");
return returnVal;
}
});
}
}
package com.sky.proxy.dynamicproxy;
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
// 创建目标对象
ITeacherDao target = new TeacherDao();
// 给目标对象,创建代理对象,可以转成ITeacherDao
ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance();
System.out.println(" proxyInstance = " + proxyInstance);
System.out.println(" proxyInstance = " + proxyInstance.getClass());
// 通过代理对象,调用目标对象中的方法
proxyInstance.teach();
proxyInstance.sayHi(" JERRY ");
}
}
JDK代理开始。。。
JDK代理提交。。。
proxyInstance = com.sky.proxy.dynamicproxy.TeacherDao@5cad8086
proxyInstance = class com.sun.proxy.$Proxy0
JDK代理开始。。。
老师授课中 。。。。
JDK代理提交。。。
JDK代理开始。。。
hello JERRY
JDK代理提交。。。
****
Cglib代理
Cglib代理实现步骤
1)需要引入Cglib的jar包
以上是教学视频中引入的jar包,我是引入的下面的jar包
jar://D:/test/cglib-nodep-3.3.0.jar!/
两者最终实现的效果都是一样的。
1)在内存中动态构建子类,注意代理的类不能为final,否则会报错。java.lang.IllegalArgumentException.
2)目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法。
案例类图
代码实现
package com.sky.proxy.cglibproxy;
/**
* 目标对象
*/
public class TeacherDao {
public String teach() {
System.out.println(" 老师授课中 。。。。我是cglib代理,不需要实现接口 ");
return " hello ";
}
}
package com.sky.proxy.cglibproxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* 代理工厂
*/
public class ProxyFactory implements MethodInterceptor {
private Object target; // 聚合一个目标对象(也就是被代理的对象)
// 构造器,对target进行初始化
public ProxyFactory(Object target) {
this.target = target;
}
// 返回一个代理对象 是 target 对象的代理对象
public Object getProxyInstance(){
// 1.创建一个工具类
Enhancer enhancer = new Enhancer();
// 2.设置父类
enhancer.setSuperclass(target.getClass());
// 3.设置回调函数
enhancer.setCallback(this); // 这里的this就是intercept方法自己
// 4.创建子类对象,即代理对象
return enhancer.create();
}
// 重写intercept方法,会调用目标对象的方法
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println(" cglib代理模式。。。开始 ");
Object returnVal = method.invoke(target,objects);
System.out.println(" cglib代理模式。。。提交 ");
return returnVal;
}
}
package com.sky.proxy.cglibproxy;
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
TeacherDao target = new TeacherDao();
TeacherDao proxyInstance = (TeacherDao) new ProxyFactory(target).getProxyInstance();
String result = proxyInstance.teach();
System.out.println(" 返回结果 : " + result);
}
}
cglib代理模式。。。开始
老师授课中 。。。。我是cglib代理,不需要实现接口
cglib代理模式。。。提交
返回结果 : hello
****
代理模式的变体
分类:
设计模式
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY