当前位置: 首页 > news >正文

常州seo建站秦皇岛网站建设公司

常州seo建站,秦皇岛网站建设公司,菏泽市建设银行网站,wordpress页面特效面试官问 Spring AOP 中两种代理模式的区别?很多初学者栽了跟头#xff0c;快来一起学习吧#xff01; 代理模式是一种结构性设计模式。为对象提供一个替身#xff0c;以控制对这个对象的访问。即通过代理对象访问目标对象#xff0c;并允许在将请求提交给对象前后进行一…面试官问 Spring AOP 中两种代理模式的区别?很多初学者栽了跟头快来一起学习吧 代理模式是一种结构性设计模式。为对象提供一个替身以控制对这个对象的访问。即通过代理对象访问目标对象并允许在将请求提交给对象前后进行一些处理。 被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象。 代理模式主要有三种不同的形式 静态代理由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的 .class 文件就已经存在了动态代理JDK 代理、接口代理在程序运行时运用反射机制动态创建而成动态就是在程序运行时生成的而不是编译时。cglib 代理可以在内存动态的创建对象而不是实现接口属于动态代理的范畴 为什么要控制对于某个对象的访问呢举个例子有这样一个消耗大量系统资源的巨型对象 你只是偶尔需要使用它 并非总是需要。 你可以实现延迟初始化在实际有需要时再创建该对象。对象的所有客户端都要执行延迟初始代码。不幸的是 这很可能会带来很多重复代码。 在理想情况下 我们希望将代码直接放入对象的类中 但这并非总是能实现比如类可能是第三方封闭库的一部分。 代理模式建议新建一个与原服务对象接口相同的代理类 然后更新应用以将代理对象传递给所有原始对象客户端。代理类接收到客户端请求后会创建实际的服务对象 并将所有工作委派给它。 代理将自己伪装成数据库对象 可在客户端或实际数据库对象不知情的情况下处理延迟初始化和缓存查询结果的工作。 这有什么好处呢如果需要在类的主要业务逻辑前后执行一些工作 你无需修改类就能完成这项工作。由于代理实现的接口与原类相同 因此你可将其传递给任何一个使用实际服务对象的客户端。 1.服务接口 Service Interface 声明了服务接口。代理必须遵循该接口才能伪装成服务对象。服务 Service 类提供了一些实用的业务逻辑。代理 Proxy 类包含一个指向服务对象的引用成员变量。代理完成其任务 例如延迟初始化、 记录日志、 访问控制和缓存等 后会将请求传递给服务对象。通常情况下 代理会对其服务对象的整个生命周期进行管理。客户端 Client 能通过同一接口与服务或代理进行交互 所以你可在一切需要服务对象的代码中使用代理。 打游戏有代练、买卖房子有中介代理、再比如一般公司投互联网广告也可以找代理公司这里的代练、中介、广告代理公司扮演的角色都是代理。 这里举个更接近程序员的例子比如有些变态的公司不允许在公司刷微博看视频可以通过一层代理来限制我们访问这些网站。 废话不多说先来个静态代理。 1、定义网络接口 public interface Internet {void connectTo(String serverHost) throws Exception; }2、真正的网络连接 public class RealInternet implements Internet{Overridepublic void connectTo(String serverHost) throws Exception {System.out.println(Connecting to serverHost);} }3、公司的网络代理 public class ProxyInternet implements Internet {//目标对象通过接口聚合private Internet internet;// 通过构造方法传入目标对象public ProxyInternet(Internet internet){this.internet internet;}//网络黑名单private static ListString bannedSites;static{bannedSites new ArrayListString();bannedSites.add(bilibili.com);bannedSites.add(youtube.com);bannedSites.add(weibo.com);bannedSites.add(qq.com);}Overridepublic void connectTo(String serverhost) throws Exception {// 添加限制功能if(bannedSites.contains(serverhost.toLowerCase())){throw new Exception(Access Denied:serverhost);}internet.connectTo(serverhost);} }4、客户端验证 public class Client {public static void main(String[] args) {Internet internet new ProxyInternet(new RealInternet());try {internet.connectTo(so.com);internet.connectTo(qq.com);} catch (Exception e) {System.out.println(e.getMessage());}} }5、输出 Connecting to so.com Access Denied:qq.com不能访问娱乐性网站但是可以用 360 搜索SO 靠谱哈哈 在不修改目标对象的前提下可以通过代理对象对目标对象功能扩展 代理使客户端不需要知道实现类是什么怎么做的而客户端只需知道代理即可解耦合对于如上的客户端代码RealInterner() 可以应用工厂将它隐藏。 代理类和委托类实现了相同的接口代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。如果接口增加一个方法除了所有实现类需要实现这个方法外所有代理类也需要实现此方法。增加了代码维护的复杂度。代理对象只服务于一种类型的对象如果要服务多类型的对象。势必要为每一种对象都进行代理静态代理在程序规模稍大时就无法胜任了。 静态代理会产生很多静态类所以我们要想办法可以通过一个代理类完成全部的代理功能这就引出了动态代理。 代理对象不需要实现接口但是目标对象要实现接口否则不能用动态代理代理对象的生成是通过 JDK 的 API反射机制动态的在内存中构建代理对象 在 Java 中要想实现动态代理机制需要 java.lang.reflect.InvocationHandler 接口和 java.lang.reflect.Proxy 类的支持 1、网络接口不变 public interface Internet {void connectTo(String serverHost) throws Exception; }2、真正的网络连接也不会改变 public class RealInternet implements Internet{Overridepublic void connectTo(String serverHost) throws Exception {System.out.println(Connecting to serverHost);} }3、动态代理需要实现 InvocationHandler我们用 Lambda 表达式简化下 public class ProxyFactory {/*** 维护一个目标对象**/private Object target;/*** 构造器初始化目标对象**/public ProxyFactory(Object target) {this.target target;}public Object getProxyInstance() {/**被代理对象target通过参数传递进来通过target.getClass().getClassLoader()获取ClassLoader对象然后通过target.getClass().getInterfaces()获取它实现的所有接口再将target包装到实现了InvocationHandler接口的对象中。通过newProxyInstance函数我们就获得了一个动态代理对象。*/return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if(bannedSites.contains(args[0].toString().toLowerCase())){throw new Exception(Access Denied:args[0]);}//反射机制调用目标对象的方法Object obj method.invoke(target, args);return obj;}});}private static ListString bannedSites;static{bannedSites new ArrayListString();bannedSites.add(bilibili.com);bannedSites.add(youtube.com);bannedSites.add(weibo.com);bannedSites.add(qq.com);} }4、客户端 public class Client {public static void main(String[] args) {Internet internet new ProxyInternet(new RealInternet());try {internet.connectTo(360.cn);internet.connectTo(qq.com);} catch (Exception e) {System.out.println(e.getMessage());}} }动态代理的方式中所有的函数调用最终都会经过 invoke 函数的转发因此我们就可以在这里做一些自己想做的操作比如日志系统、事务、拦截器、权限控制等。 静态代理和 JDK 代理模式都要求目标对象实现一个接口但有时候目标对象只是一个单独的对象并没有实现任何接口这个时候就可以使用目标对象子类来实现代理这就是 cglib 代理。 cglib(Code Generation Library)是一个基于ASM的字节码生成库它允许我们在运行时对字节码进行修改和动态生成。cglib 通过继承方式实现代理。它广泛的被许多AOP的框架使用比如我们的 Spring AOP。cglib 包的底层是通过使用字节码处理框架 ASM 来转换字节码并生成新的类。cglib 代理也被叫做子类代理它是在内存中构建一个子类对象从而实现目标对象功能扩展。 添加 cglib 依赖 dependencygroupIdcglib/groupIdartifactIdcglib/artifactIdversion3.3.0/version /dependency1、不需要接口 public class RealInternet{public void connectTo(String serverHost) {System.out.println(Connecting to serverHost);} }2、代理工厂类 public class ProxyFactory implements MethodInterceptor {private Object target;public ProxyFactory(Object target){this.target target;}Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println(cglib 代理开始可以添加逻辑);Object obj method.invoke(target,objects);System.out.println(cglib 代理结束);return obj;}public Object getProxyInstance(){//工具类类似于JDK动态代理的Proxy类Enhancer enhancer new Enhancer();//设置父类enhancer.setSuperclass(target.getClass());//设置回调函数enhancer.setCallback(this);//创建子类对象即代理对象return enhancer.create();} }3、客户端 public class Client {public static void main(String[] args) {//目标对象RealInternet target new RealInternet();//获取代理对象,并且将目标对象传递给代理对象RealInternet internet (RealInternet) new ProxyFactory(target).getProxyInstance();internet.connectTo(so.cn);} }4、输出 cglib 代理开始可以添加逻辑 Connecting to so.cn cglib 代理结束使用代理模式的方式多种多样 我们来看看最常见的几种。 延迟初始化 虚拟代理如果你有一个偶尔使用的重量级服务对象 一直保持该对象运行会消耗系统资源时 可使用代理模式。你无需在程序启动时就创建该对象 可将对象的初始化延迟到真正有需要的时候。访问控制 保护代理如果你只希望特定客户端使用服务对象 这里的对象可以是操作系统中非常重要的部分 而客户端则是各种已启动的程序 包括恶意程序 此时可使用代理模式。代理可仅在客户端凭据满足要求时将请求传递给服务对象。本地执行远程服务 远程代理适用于服务对象位于远程服务器上的情形。在这种情形中 代理通过网络传递客户端请求 负责处理所有与网络相关的复杂细节。记录日志请求 日志记录代理适用于当你需要保存对于服务对象的请求历史记录时。代理可以在向服务传递请求前进行记录。缓存请求结果 缓存代理适用于需要缓存客户请求结果并对缓存生命周期进行管理时 特别是当返回结果的体积非常大时。代理可对重复请求所需的相同结果进行缓存 还可使用请求参数作为索引缓存的键值。比如请求图片、文件等资源时先到代理缓存取如果没有就去公网取并缓存到代理服务器智能引用可在没有客户端使用某个重量级对象时立即销毁该对象。代理会将所有获取了指向服务对象或其结果的客户端记录在案。代理会时不时地遍历各个客户端 检查它们是否仍在运行。如果相应的客户端列表为空 代理就会销毁该服务对象 释放底层系统资源。代理还可以记录客户端是否修改了服务对象。其他客户端还可以复用未修改的对象。 AOP面向切面编程主要的的实现技术主要有 Spring AOP 和 AspectJ AspectJ 的底层技术就是静态代理用一种 AspectJ 支持的特定语言编写切面通过一个命令来编译生成一个新的代理类该代理类增强了业务类这是在编译时增强相对于下面说的运行时增强编译时增强的性能更好。AspectJ 的静态代理不像我们前边介绍的需要为每一个目标类手动编写一个代理类AspectJ 框架可以在编译时就生成目标类的“代理类”在这里加了个冒号是因为实际上它并没有生成一个新的类而是把代理逻辑直接编译到目标类里面了 Spring AOP 采用的是动态代理在运行期间对业务方法进行增强所以不会生成新类对于动态代理技术Spring AOP 提供了对 JDK 动态代理的支持以及 CGLib 的支持。 默认情况下Spring对实现了接口的类使用 JDK Proxy方式否则的话使用CGLib。不过可以通过配置指定 Spring AOP 都通过 CGLib 来生成代理类。 具体逻辑在 org.springframework.aop.framework.DefaultAopProxyFactory类中使用哪种方式生成由AopProxy 根据 AdvisedSupport 对象的配置来决定源码如下 public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {public DefaultAopProxyFactory() {}public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (!config.isOptimize() !config.isProxyTargetClass() !this.hasNoUserSuppliedProxyInterfaces(config)) {return new JdkDynamicAopProxy(config);} else {Class? targetClass config.getTargetClass();if (targetClass null) {throw new AopConfigException(TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.);} else {//如果目标类是接口且是代理类, 使用JDK动态代理类否则使用Cglib生成代理类return (AopProxy)(!targetClass.isInterface() !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));}}}private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {} }具体内容就不展开了后边整理 SpringAOP 的时候再深入。
http://www.zqtcl.cn/news/392069/

相关文章:

  • 学校网页网站模板wordpress更换域名还是之前链接
  • 市面上有什么搭建网站工作室石家庄做网站和宣传的
  • 视频图站主题 wordpress快速收录提交入口
  • 外贸视频网站投资理财网站开发
  • 专业建设网站多少钱铜川网站seo
  • 海外网站seo优化wordpress的代码逻辑
  • 怎样帮别人做网站哪有网站给光头强做面
  • 聊城营销网站建设价格网站设计论文框架
  • 成都哪家网站建设做得好介绍自己的家乡遵义网站建设
  • 阳春新农村建设网站欣赏网站
  • 永久免费企业网站建设杭州个人做网站
  • 博罗中山网站建设做网站的软件 知乎
  • 广州网站开发广州亦客网络解答wordpress换空间要改
  • 丽水企业网站开发企业erp系统是什么软件
  • 好看的网站设计个人发布信息的免费平台
  • 电商网站业务流程linux上传中文wordpress
  • 广州网站定制商家外贸seo网站推广
  • 许昌大成建设集团网站wordpress自动博客插件
  • wordpress网站地图插件中国来料加工网
  • 黑龙江做网站的公司上海企业网站建设公
  • 做公众号时图片的网站安徽建设工程造价信息网站
  • 网站开发的在淘宝上是什么类目深圳做网站的大公司
  • 手机网站 html5信阳哪里做网站
  • 网站服务器多少钱一月wordpress 博客宠物
  • 怎么制作网站游戏辽宁建设工程网
  • 网站开发好还要空间吗网站支付链接怎么做的
  • 网站制作报价图片欣赏杭州做网站价格
  • 帮人家做家务的网站host绑定网站
  • 地方门户网站盈利模式这样做微信网站
  • 企业网站要怎么做wordpress w3