您的位置:首页 > 汽车 > 时评 > 江苏市场监督管理局_全屋整装定制_今日新闻 最新消息 大事_百度地图客服人工电话

江苏市场监督管理局_全屋整装定制_今日新闻 最新消息 大事_百度地图客服人工电话

2024/11/18 19:45:21 来源:https://blog.csdn.net/2301_80389611/article/details/142388825  浏览:    关键词:江苏市场监督管理局_全屋整装定制_今日新闻 最新消息 大事_百度地图客服人工电话
江苏市场监督管理局_全屋整装定制_今日新闻 最新消息 大事_百度地图客服人工电话

代理模式

    代理模式:给某一个对象提供一个代理,并由代理对象来控制对真实对象的访问。代理模式是一种结构型设计模式。
   代理模式角色分为 3种:

  • Subject(抽象主题角色):定义代理类和真实主题的公共对外方法,通常被设计成接口;
  • RealSubject(真实主题角色):真正实现业务逻辑的类;
  • Proxy(代理主题角色):用来代理和封装真实主题;

    代理模式的结构比较简单,其核心是代理类,为了让客户端能够一致性地对待真实对象和代理对象,在代理模式中引入了抽象层。

如果根据字节码的创建时机来分类,可以分为静态代理和动态代理:

  • 所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和真实主题角色的关系在运行前就确定了。
  • 而动态代理的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以在运行前并不存在代理类的字节码文件

静态代理

假设有 UserService接口及其实现类 UserServiceImpl,我们需要在不改变实现类代码的基础上,增加日志记录的功能。

UserService:

public interface UserService {public void select();public void update();}

UserService:

public class UserServiceImpl implements UserService{public void select(){System.out.println("查询 selectById");}public void update(){System.out.println("更新 update");}
}

我们将通过静态代理对UserServiceImpl 进行功能增强,在调用 select 和 update 之前记录一些
日志。
静态代理通过 UserServiceProxy实现代理类同时也需要实现 UserService 接口

Proxy:

public class UserServiceProxy implements UserServiceprivate Userservice target;// 被代理的对象public UserServiceProxy(UserService target){this.target =target;}public void select(){before();target.select();          // 这里才实际调用真实主题角色的方法 after();}public void update(){before();target.update();                       //这里才实际调用真实主题角色的方法after();}private void before(){             // 在执行方法之前执行System.out.println(String.format("log start time [%s]",new Date()));}  private void after(){    //在执行方法之后执行System.out.println(String.format("log end time [%s]",new Date()));}
}

测试:

public class Test{public static void main(String[]args){UserService userServiceImpl=new UserServiceImpl();UserService proxy =new UserServiceProxy(userServiceImpl);proxy.select();proxy.update();}
}

         通过静态代理,我们达到了功能增强的目的,而且没有侵入原代码,这是静态代理的一个优点。
         虽然静态代理实现简单,且不侵入原代码,但是,当场景稍微复杂一些的时候,静态代理的缺点也会暴露出来。

  1. 当需要代理多个类的时候,由于代理对象要实现与目标对象一致的接口,有两种方式:
  • 只维护一个代理类,由这个代理类实现多个接口,但是这样就导致代理类过于庞大
  • 新建多个代理类,每个目标对象对应一个代理类,但是这样会产生过多的代理类

     2.当接口需要增加、删除、修改方法的时候,目标对象与代理类都要同时修改,不易维护。

动态代理

Java中两种常见的动态代理方式: JDK 原生动态代理和CGLIB 动态代理(第三方开源类库)

JDK动态代理主要涉及两个类:java.lang.reflect.Proxy和 java.lang.reflect.InvocationHandler 。我们通过编写一个调用逻辑处理器LogHandler 类案例来提供日志增强功能,并实现InvocationHandler 接口;在LogHandler 中维护一个目标对象,这个对象是被代理的对象(真实主题角色);
在 invoke()方法中编写方法调用的逻辑处理。

//动态代理的处理类
public class LogHandler implements InvocationHandler{0bject target; // 被代理的对象,实际的方法执行者public LogHandler(Object target){this.target = target;}@0verridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable{before();Object result =method.invoke(target,args);// 调用 target 的 method 方法after();return result; // 返回方法的执行结果}//调用invoke方法之前执行private void before(){System.out.println(String.format("log start time [%s]",new Date()));}//调用invoke方法之后执行private void after(){System.out.println(String.format("log end time [%s]",new Date()));}
}

测试类:

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com