- 属于结构型设计模式
- 分为三种:1.静态代理 2.动态代理 3.cglib代理
- 优点:协调调用者和被调用者,在一定程度上降低了系统的耦合度,同时起中介作用,进而保护目标对象
- 缺点:增加了代理对象,使请求的处理速度变慢,实现更加复杂
- 代理模式应用在 Spring AOP中(动态代理和cglib代理)
静态代理需要定义接口,然后进行实现
// 接口
public interface Zoo {
void enter(User user);
}
// 使用对象
@Data
@AllArgsConstructor
public class User {
private Integer id;
private String username;
}
// 目标对象
public class ZooImpl implements Zoo {
@Override
public void enter(User user) {
System.out.println(user + " enter ZooImpl");
}
}
// 代理类
public class ZooProxy implements Zoo {
private Integer num = 1;
private static final Integer MAX_NUM = 2;
/** 目标对象 **/
private Zoo zoo;
public ZooProxy(Zoo zoo) {
this.zoo = zoo;
}
@Override
public void enter(User user) {
if (num <= MAX_NUM) {
// 执行之前
System.out.println(user + " can enter");
num++;
zoo.enter(user);
// 执行之后
System.out.println(user + " left");
} else {
System.out.println(user + " is not allowed to enter");
}
}
}
// 测试类
public class Main {
public static void main(String[] args) {
ZooProxy proxy = new ZooProxy(new ZooImpl());
proxy.enter(new User(1, "stalary"));
proxy.enter(new User(2, "hawk"));
proxy.enter(new User(3, "claire"));
}
}
// 测试结果
User(id=1, username=stalary) can enter
User(id=1, username=stalary) enter ZooImpl
User(id=1, username=stalary) left
User(id=2, username=hawk) can enter
User(id=2, username=hawk) enter ZooImpl
User(id=2, username=hawk) left
User(id=3, username=claire) is not allowed to enter
动态代理不需要实现接口,但是需要指定接口类型,即目标对象需要实现接口
// ClassLoader loader:目标对象使用的类加载器
// Class<?>[] interfaces:目标对象实现的接口类型
// InvocationHandler:事件处理方法
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
// 检验处理方法不为空
Objects.requireNonNull(h);
// 将传入的接口克隆
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// 安全检查
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
// 查找或生成指定的代理类
Class<?> cl = getProxyClass0(loader, intfs);
try {
if (sm != null) {
// 安全检查
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
// 获取处理器的构造函数
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
// 当构造器不可修改时,修改权限
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
// 返回实例
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
// 代理工厂
public class ProxyFactory {
// 目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
public Object getProxyInstance() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
(proxy, method, args) -> {
System.out.println("动态代理开始执行");
Object value = method.invoke(target, args);
System.out.println("动态代理执行完毕");
return value;
}
);
}
}
// 测试类
public class Main1 {
public static void main(String[] args) {
Zoo zoo = new ZooImpl();
Zoo proxy = (Zoo) new ProxyFactory(zoo).getProxyInstance();
proxy.enter(new User(1, "stalary"));
proxy.enter(new User(2, "hawk"));
proxy.enter(new User(3, "claire"));
}
}
// 结果
动态代理开始执行
User(id=1, username=stalary) enter ZooImpl
动态代理执行完毕
动态代理开始执行
User(id=2, username=hawk) enter ZooImpl
动态代理执行完毕
动态代理开始执行
User(id=3, username=claire) enter ZooImpl
动态代理执行完毕
可使用在目标对象未使用接口时,但是需要依赖于cglib的jar包
// 代理类,实现MethodInterceptor
public class ProxyCGLIB implements MethodInterceptor {
private Object target;
public ProxyCGLIB(Object target) {
this.target = target;
}
public Object getProxyInstance() {
//1.工具类
Enhancer en = new Enhancer();
//2.设置父类
en.setSuperclass(target.getClass());
//3.设置回调函数
en.setCallback(this);
//4.创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib开始执行");
Object value = method.invoke(target, args);
System.out.println("cglib执行完毕");
return value;
}
}
// 目标对象
public class NormalZoo {
public void enter(User user) {
System.out.println(user + " enter NormalZoo");
}
}
// 测试方法
public class Main2 {
public static void main(String[] args) {
NormalZoo target = new NormalZoo();
NormalZoo proxy = (NormalZoo) new ProxyCGLIB(target).getProxyInstance();
proxy.enter(new User(1, "stalary"));
proxy.enter(new User(2, "hawk"));
proxy.enter(new User(3, "claire"));
}
}
// 测试结果
cglib开始执行
User(id=1, username=stalary) enter NormalZoo
cglib执行完毕
cglib开始执行
User(id=2, username=hawk) enter NormalZoo
cglib执行完毕
cglib开始执行
User(id=3, username=claire) enter NormalZoo
cglib执行完毕