JAVA语言中的代理模式
代理可以进一步划分为静态代理和动态代理,代理模式在实际的生活中场景很多,例如中介、律师、代购等行业,都是简单的代理逻辑,在这个模式下存在两个关键角色:
代理对象角色:内部含有目标对象的引用,可以操作目标对象
一、静态代理
目标对象角色
public class Target {public void execute(){System.out.println("Target execute...");}
}
代理对象角色
public class ProxyObj {private Target target;public ProxyObj(Target target){this.target=target;}public void invoke(){before();target.execute();after();}public void before(){System.out.println("before...");}public void after(){System.out.println("after...");}
}
public class Proxy {public static void main(String[] args) {Target target = new Target();ProxyObj proxy = new ProxyObj(target);proxy.invoke();}
}
代理模式的本质是在目标对象的方法前后置入增强操作
二、动态代理
首先看两个核心类,这里简述下概念,看完基本过程再细聊:
-
Proxy-创建代理对象,核心参数:
- ClassLoader:(目标类)加载器;
- Interfaces:(目标类)接口数组;
- InvocationHandler:代理调用机制;
-
InvocationHandler-代理类调用机制:
- invoke:这个上篇说的反射原理;
- method:反射类库中的核心API;
目标对象和接口
interface IUser {Integer update (String name) ;
}
class UserService implements IUser {@Overridepublic Integer update(String name) {Integer userId = 99 ;System.out.println("UserId="+userId+";updateName="+name);return userId ;}
}
代理对象执行机制
class UserHandler implements InvocationHandler {private Object target ;public UserHandler (Object target){this.target = target ;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("before()...");Object result = method.invoke(target, args);System.out.println("after()...");return result;}
}
具体使用:
public class Proxy02 {public static void main(String[] args) {/ 生成$Proxy0的class文件*/System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");/ 目标对象信息*/IUser userService = new UserService();ClassLoader classLoader = userService.getClass().getClassLoader();Class<?>[] interfaces = UserService.class.getInterfaces() ;/ 创建代理对象*/InvocationHandler userHandler = new UserHandler(userService);/ 代理类对象名* proxyClassName=com.java.proxy.$Proxy0*/String proxyClassName = Proxy.newProxyInstance(classLoader,interfaces,userHandler).getClass().getName();System.out.println("proxyClassName="+proxyClassName);/ 具体业务实现模拟*/IUser proxyUser1 = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);IUser proxyUser2 = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);proxyUser1.update("cicada") ;proxyUser2.update("smile") ;}
}
JDK源码
IUser proxyUser = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);
Proxy提供的静态方法newProxyInstance()
,通过各个参数的传入,构建一个新的代理Class对象,即$Proxy0类的结构信息,这里再回首看下三个核心参数:
-
ClassLoader:基于JVM运行过程,所以需要获取目标类UserService的类加载器;
-
Interfaces:目标类UserService实现的接口,从面向对象来考虑,接口与实现分离,代理类通过实现IUser接口,模拟目标类的需求;
-
InvocationHandler:代理类提供的功能封装即UserHandler,可以在目标方法调用前后做增强处理