Proxy 是一种结构设计模型, 主要解决对象直接访问带来的问题, 代理又分为静态代理和动态代理(JDK 代理, CGLIB 代理.
静态代理: 又程序创建的代理类, 或者特定的工具类, 在平时开发中经常用到这种代理模式, 这种一般在程序运行前就已经生成对应的 class 文件;
动态代理: 在程序运行时通过反射机制动态创建.
下面通过一个场景实现以下三种代理方式
步骤一: 定义商店接口(Subject)
步骤二: 个人店家运营(RealSubject)
步骤三: 平台运营(proxy)
步骤四: 个体消费(client)
几种代理方式都会用到 Subject,RealSubject, 现在这里定义
Store.java(Subject): 定义两个接口 operate(运营),business(交易).
- public interface Store {
- /**
- * 店铺运营
- */
- public void operate();
- /**
- * 店铺交易
- */
- public void business();
- }
PersonStore.java(RealSubject) 单个用户运营
- public class PersonStore implements Store {
- @Override
- public void operate() {
- System.out.println("个人商店运营");
- }
- @Override
- public void business() {
- System.out.println("个人商店交易");
- }
- }
静态代理
静态代理的实现比较简单, 代理类通过实现与目标对象相同的接口, 并在类中维护一个代理对象, 这种场景用于个体商家比较少的情况, 如果多的话代理类十分繁多, 不易维护
创建静态代理类
ProxyStroe.java(proxy): 在代理平台运营是收取管理费用 100, 这个代理类需要实现 Store 接口, 并制定目标类 target(PersonStore).
- public class ProxyStroe implements Store{
- private Store personStore = new PersonStore();
- @Override
- public void operate() {
- System.out.println("收取管理费用 100 元");
- personStore.operate();
- }
- @Override
- public void business() {
- personStore.business();
- }
- }
静态代理调用
StaticConsumer.java(client): 通过创建 ProxyStroe 去代理 PersonStore, 并进行操作.
- public class StaticConsumer {
- public static void main(String[] args) {
- ProxyStroe store = new ProxyStroe();
- store.operate();
- store.business();
- }
- }
动态代理
JDK 代理
动态代理类是通过接口实现的, 利用拦截器 (拦截器必须实现 InvocationHanlder) 加上反射机制生成一个实现代理接口的匿名类,
在调用具体方法前调用 InvokeHandler 来处理.
创建 jdk 代理类
JDKStoreHandler.java(proxy): 通过实现 InvocationHandler 接口的 invoke 方法, 在里面进行反射调用, newProxyInstanse 通过目标对象创建真是对象.
- public class JDKStoreHandler implements InvocationHandler {
- /**
- * 目标对象
- */
- private Object targetObject;
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- if("operate".equals(method.getName())){
- System.out.println("收取管理费用 100 元");
- }
- return method.invoke(targetObject, args);
- }
- /**
- *
- * @param targetObject
- * @return
- */
- public Object newProxyInstanse(Object targetObject){
- this.targetObject = targetObject;
- return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this);
- }
- }
JDK 代理对象调用
JDKDynamicConsumer.java(proxy): 通过 JDKStoreHandler 的 newProxyInstanse 创建真实目标对象, 并调用接口的方法
- public class JDKDynamicConsumer {
- public static void main(String[] args) {
- Store store = (Store)new JDKStoreHandler().newProxyInstanse(new PersonStore());
- store.operate();
- store.business();
- }
- }
CGLIB 代理
cglib 动态代理是利用 asm 开源包, 对代理对象类的 class 文件加载进来, 通过修改其字节码生成子类来处理.
创建 cglib 代理对象
CglibProxy.java(proxy): 需要实现 MethodInterceptor 的 intercept 方法, 并进行反射调用. 通过 createProxyObject 创建真实对象, 这里是根据目标对象直接生成对象.
- public class CglibProxy implements MethodInterceptor{
- /**
- * CGlib 需要代理的目标对象
- */
- private Object targetObject;
- public Object createProxyObject(Object targetObject){
- this.targetObject = targetObject;
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(targetObject.getClass());
- enhancer.setCallback(this);
- Object proxyObj = enhancer.create();
- return proxyObj;
- }
- @Override
- public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
- if("operate".equals(method.getName())){
- System.out.println("收取管理费用 100 元");
- }
- return method.invoke(targetObject, objects);
- }
- }
CGLib 代理对象调用
CglibDynamicConsumer.java(client): 通过 CglibProxy 的 createProxyObject 创建真实目标对象, 对进行方法调用
- public class CglibDynamicConsumer {
- public static void main(String[] args) {
- Store store = (Store)new CglibProxy().createProxyObject(new PersonStore());
- store.operate();
- store.business();
- }
- }
源码已上传: https://github.com/itrickzhang/proxy-demo
来源: https://www.cnblogs.com/itrickzhang/p/11495564.html