1、概念
由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
优点:
- 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
- 代理对象可以扩展目标对象的功能;
- 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度,增加了程序的可扩展性;
缺点: - 代理模式会造成系统设计中类的数量增加
- 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;
- 增加了系统的复杂度;
2、实现
2.1、静态代理
由程序员创建代理类或特定工具自动生成源代码再对其编译,在程序运行前代理类的 .class 文件就已经存在了。
package com.mine.design.proxy.staticproxy;
public interface ITarget {
void operation();
}
package com.mine.design.proxy.staticproxy;
public class Target implements ITarget {
public void operation() {
System.out.println("目标执行");
}
}
package com.mine.design.proxy.staticproxy;
public class Proxy implements ITarget {
private ITarget target;
public Proxy(ITarget target) {
this.target = target;
}
public void operation() {
System.out.println("代理执行前");
target.operation();
System.out.println("代理执行后");
}
}
package com.mine.design.proxy.staticproxy;
public class Client {
public static void main(String[] args) {
ITarget target = new Target();
ITarget proxy = new Proxy(target);
proxy.operation();
}
}
2.2、动态代理
在程序运行时,运用反射机制动态创建而成。动态代理也叫JDK代理或者接口代理。它有以下特点:
- 代理对象不需要实现接口。
- 代理对象的生成是利用 JDK 的 API 动态的在内存中构建代理对象。
- 能在代码运行时动态地改变某个对象的代理,并且能为代理对象动态地增加方法、增加行为。
package com.mine.design.proxy.dynamicproxy;
public interface ITarget {
void operation();
}
package com.mine.design.proxy.dynamicproxy;
public class Target implements ITarget {
public void operation() {
System.out.println("目标执行");
}
}
package com.mine.design.proxy.dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory implements InvocationHandler {
private Object target;
public Object getInstance(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理前");
Object result = method.invoke(this.target, args);
System.out.println("代理后");
return result;
}
}
package com.mine.design.proxy.dynamicproxy;
public class Client {
public static void main(String[] args) {
ITarget target = new Target();
ProxyFactory factory = new ProxyFactory();
ITarget instance = (ITarget) factory.getInstance(target);
instance.operation();
System.out.println(instance.getClass());
}
}
package com.mine.design.proxy.dynamicproxy;
public class Client {
public static void main(String[] args) {
ITarget target = new Target();
ProxyFactory factory = new ProxyFactory();
ITarget instance = (ITarget) factory.getInstance(target);
instance.operation();
System.out.println(instance.getClass());
}
}
2.3、cglib代理
cglib是一个强大的高性能的代码生成包,广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。
cglib包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。
package com.mine.design.proxy.cglib;
public class Target {
public void operation() {
System.out.println("目标执行");
}
}
package com.mine.design.proxy.cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class ProxyFactory implements MethodInterceptor {
private Object object;
public Object getProxy(Object object) {
this.object = object;
// 1、创建一个工具类
Enhancer enhancer = new Enhancer();
// 2、设置父类
enhancer.setSuperclass(this.object.getClass());
// 3、设置回调函数
enhancer.setCallback(this);
// 4、创建代理对象并返回
return enhancer.create();
}
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("cglib 代理开始");
Object result = method.invoke(this.object, args);
System.out.println("cglib 代理结束");
return result;
}
}
package com.mine.design.proxy.cglib;
public class Client {
public static void main(String[] args) {
Target target = new Target();
ProxyFactory factory = new ProxyFactory();
Target proxy = (Target)factory.getProxy(target);
proxy.operation();
System.out.println(proxy.getClass());
}
}