设计模式-代理模式
·
设计模式-代理模式
介绍
代理模式分为:静态代理、动态代理。
代理模式是给某一个对象提供一个代理对象,代理对象拥有原对象的引用,代理对象替原对象去执行这个行为。通俗的来讲代理模式就是我们生活中常见的中介。
1 静态代理模式
1.1 UML类图

1.2 示例
代码示例:代理点coffee
- 创建服务类接口
public interface Coffee {
void orderCoffee();
}
- 瑞幸咖啡
public class LuckinCoffee implements Coffee {
@Override
public void orderCoffee() {
System.out.print(" 瑞幸coffee");
}
}
- 星巴克
public class StarbucksCoffee implements Coffee {
@Override
public void orderCoffee() {
System.out.print(" 星巴克coffee");
}
}
- 代理对象
public class CoffeeProxy implements Coffee {
public Coffee coffee;
public CoffeeProxy(Coffee coffee) {
this.coffee = coffee;
}
public CoffeeProxy() {
this.coffee = new StarbucksCoffee();
}
@Override
public void orderCoffee() {
System.out.print("加糖");
this.coffee.orderCoffee();
System.out.println("");
}
}
- client
public class Client {
public static void main(String[] args) {
CoffeeProxy coffeeProxy = new CoffeeProxy();
coffeeProxy.orderCoffee();
CoffeeProxy coffeeProxy1 = new CoffeeProxy(new LuckinCoffee());
coffeeProxy1.orderCoffee();
}
}
输出
加糖 星巴克coffee
加糖 瑞幸coffee
2 动态代理模式
动态代理实现方式:JDK动态代理、GDLib动态代理。
2.1 JDK动态代理
JDK动态代理,代理对象要实现接口InvocationHandler
2.1.1 UML类图

2.1.2 代码
- 动态代理对象 class JdkProxy
public class JdkProxy implements InvocationHandler {
// 目标对象引用
private Object target;
// 通过构造方法将目标对象注入到当前代理对象中
public JdkProxy(Object target) {
super();
this.target = target;
}
/**
* JDK动态生成目标对象target的一个代理类
*
* @return
*/
public Object getProxy() {
// 如何生成一个代理类呢?
// 1、编写源文件(java文件)----目录类接口interface实现类(调用了目标对象的方法)
// 2、编译源文件为class文件
// 3、将class文件加载到JVM中(ClassLoader)
// 4、将class文件对应的对象进行实例化(反射)
/**
* Proxy是jdk中的api
* 参数1:目标对象的类加载器
* 参数2:目标对象的接口
* 参数3:代理对象执行器处理器,当前对象invoke方法代理执行,一般传入当前对象this
*/
Object proxyObject = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
return proxyObject;
}
/**
* 代理对象会执行的方法
* @param proxy 代理对象
* @param method 代理执行的方法
* @param args 参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("这是jdk的代理方法");
// 下面的代码,是反射中的API用法
// 该行代码,实际调用的是[目标对象]
Object invoke = method.invoke(this.target, args);
return invoke;
}
}
- Client
public class Client {
public static void main(String[] args) {
// 1、创建目标对象
Coffee service = new LuckinCoffee();
// 2、生成代理对象
JdkProxy proxyFactory = new JdkProxy(service);
// 得到代理对象
Coffee proxy = (Coffee) proxyFactory.getProxy()
// 3、调用目标对象的方法
service.orderCoffee();
System.out.println("===============");
// 4、调用代理对象的方法
proxy.orderCoffee();
}
}
输出
瑞幸coffee
===============
这是jdk的代理方法
瑞幸coffee
2.2 GCLib动态代理
GCLib动态代理要使用到两个jar包
- cglib-2.2.2.jar
- asm-3.3.1.jar
下载链接地址 提取码:b5ad
2.2.1 UML类图

2.2.2 代码
- CGLib动态代理技术实现 它是基于继承的方式实现 CGLibProxy
public class CgLibProxy implements MethodInterceptor {
/**
* @param clazz
* @return
*/
public Object getProxyByCgLib(Class clazz) {
// 创建增强器
Enhancer enhancer = new Enhancer();
// 设置需要增强的类的类对象
enhancer.setSuperclass(clazz);
// 设置回调函数
enhancer.setCallback(this);
// 获取增强之后的代理对象
return enhancer.create();
}
/***
* Object proxy:这是代理对象,也就是[目标对象]的子类
* Method method:[目标对象]的方法
* Object[] arg:参数
* MethodProxy methodProxy:代理对象的方法
*/
@Override
public Object intercept(Object proxy, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable {
// 因为代理对象是目标对象的子类
// 该行代码,实际调用的是父类目标对象的方法
System.out.println("这是cglib的代理方法");
// 通过调用子类[代理类]的invokeSuper方法,去实际调用[目标对象]的方法
Object returnValue = methodProxy.invokeSuper(proxy, arg);
// 代理对象调用代理对象的invokeSuper方法,而invokeSuper方法会去调用目标类的invoke方法完成目标对象的调用
return returnValue;
}
}
- Client
public class Client {
public static void main(String[] args) {
Coffee coffee = new LuckinCoffee();
// 生成代理对象
CgLibProxy cgLibProxy = new CgLibProxy();
Coffee coffeProxy = (Coffee) cgLibProxy.getProxyByCgLib(coffee.getClass());
// 调用目标对象的方法
coffee.orderCoffee();
System.out.println("===============");
// 调用代理对象的方法
coffeProxy.orderCoffee();
}
}
输出
瑞幸coffee
===============
这是cglib的代理方法
瑞幸coffee
3 总结
- 静态代理模式与装饰模式在代码结构上很类似。在使用上如何去区别呢?装饰模式主要是对对象装饰,代理模式而是行为上的代理执行。比如对一个销售产品的包装行为,使用装饰模式;对产品销售的行为,使用代理模式。
- 动态代理,JDK动态代理与GCLib动态代理主要的区别是实现方式,对于业务流程的使用上没有差异。动态代理proxy在执行方法,会回调方法invoke(Object proxy, Method method, Object[] args)或intercept(Object proxy, Method method, Object[] arg, MethodProxy methodProxy),在该方法中新增增强行为的代码,通过反射的方式执行原对象的行为。
更多推荐

所有评论(0)