设计模式 之 代理模式
1. 关于java - 代理模式
- 代理模式的组成:被代理类 和 代理类
2. 静态代理
- 代理类对象,通过聚合被代理类对象,调用对方的方法。eg: Thread的run方法实现。
- 主要组成:接口 、实现类 和 代理类。
其中接口定义标准,是为了使代理更加规范可控,以及实现多级代理,实现类 也就是被代理类。
package com.demo.design.proxy;
/**
* 代理模式组成:接口、实现类、代理类
* 代理模式-静态代理:通过聚合持有被代理类实例,进行功能增强. eg: Thread的run方法的实现
*/
public class ProxyPatternDemo {
public static void main(String[] args) {
Movable proxyObj = new ProxyMovable(new Bike());
proxyObj.move();
}
}
/**
* 接口:可移动的
*/
interface Movable {
void move();
}
/**
* 被代理类(实现类):自行车
*/
class Bike implements Movable {
@Override
public void move() {
System.out.println(String.format("I am %s, speed %d km/h .", this.getClass().getName(), 20));
}
}
/**
* 代理类(静态代理)
*/
class ProxyMovable implements Movable {
private Movable moveObj;
ProxyMovable(Movable moveObj) {
this.moveObj = moveObj;
}
@Override
public void move() {
System.out.println("proxy handler start------");
if (moveObj != null) {
moveObj.move();
}
System.out.println("proxy handler end------");
}
}
3. 动态代理
- 通过动态生成代理类,进行代理。
3.1 JDK的Proxy类
- 通过接口动态生成代理类,聚合被代理类对象,调用对方的方法。
- 主要组成:接口 、实现类 、 代理类 、 处理器。
其中接口定义标准,用来生成代理类,以及实现多级代理 ,处理器 用来聚合被代理类对象,调用对方的方法。
package com.demo.design.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 代理模式组成:接口、实现类、代理类、处理器。
* 代理模式-动态代理:用JDK的Proxy类,通过接口创建代理对象(类加载器、接口、处理类实例)进行代理,处理类进行功能增强. eg: spring aop 功能
* 缺点:必须有接口实现,根据接口生成代理类
*/
public class ProxyPatternDemo {
public static void main(String[] args) {
// 項目目录下,会保存生成的代理对象(不是target目录下)
System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
proxy3();
}
/**
* 代理方法3
*/
private static void proxy3() {
InvocationHandler handler = new LogHandler(new Bike());
Movable proxyObj = (Movable) Proxy.newProxyInstance(Movable.class.getClassLoader(), new Class[]{Movable.class}, handler);
proxyObj.move();
}
}
/**
* 接口:可移动的
*/
interface Movable {
void move();
}
/**
* 被代理类(实现类):自行车
*/
class Bike implements Movable {
@Override
public void move() {
System.out.println(String.format("I am %s, speed %d km/h .", this.getClass().getName(), 20));
}
}
/**
* 处理类:日志处理
*/
class LogHandler implements InvocationHandler {
Movable moveObj;
public LogHandler(Movable moveObj) {
this.moveObj = moveObj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(String.format("proxy %s method start------", method.getName()));
Object result = method.invoke(moveObj, args);
System.out.println(String.format("proxy %s method end------", method.getName()));
return result;
}
}
3.1 cglib类库
- 通过生成被代理类的子类,进行方法重写。
- 主要组成:实现类 、 代理类 、 方法拦截器(处理器)。
方法拦截器 用做代理方法实现,为子类生成做准备的。
package com.demo.design.proxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* 代理模式组成:实现类、代理类
* 代理模式-动态代理:通过生成被代理类的子类,进行方法重写,实现功能增强. eg: spring aop 功能
* 缺点:必须有接口实现,根据接口生成代理类
*/
public class ProxyPatternDemo {
public static void main(String[] args) {
// 項目目录下,会保存生成的代理对象(不是target目录下)
System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
proxy();
}
/**
* 代理创建过程
*/
private static void proxy() {
Enhancer enhancer = new Enhancer(); // 增强器
enhancer.setSuperclass(Bike.class); // 设置父类
enhancer.setCallback(new LogMethodInterceptor()); // 设置方法拦截处理器
Bike bike = (Bike) enhancer.create();
bike.move();
}
}
/**
* 被代理类:自行车
*/
class Bike {
public void move() {
System.out.println(String.format("I am %s, speed %d km/h .", this.getClass().getName(), 20));
}
}
/**
* 方法拦截处理器
*/
class LogMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println(String.format("proxy %s method start------", method.getName()));
Object result = methodProxy.invokeSuper(o, objects);
System.out.println(String.format("proxy %s method end------", method.getName()));
return result;
}
}
4. asm 和 instrument
- asm:通过修改二进制代码,实现对类定义的操作修改(jdk 和 cglib 的动态代理也是用这个实现的)。
- instrument :在类字节码载入JVM前,通过修改二进制代码,实现对类定义进行操作修改。