wap网站用什么服务器网站系统模板
- 作者: 多梦笔记
- 时间: 2026年02月18日 08:52
当前位置: 首页 > news >正文
wap网站用什么服务器,网站系统模板,wordpress tdk修改,长春搜索排名公司文章目录 第五章 结构型模式5.1 代理模式5.1.1 代理模式介绍5.1.2 代理模式原理5.1.3 静态代理实现5.1.4 JDK动态代理5.1.4.1 JDK动态代理实现5.1.4.2 类是如何动态生成的5.1.4.3 代理类的调用过程 5.1.5 cglib动态代理5.1.5.1 cglib动态代理实现5.1.5.2 cglib代理流程 5.1.6 代… 文章目录 第五章 结构型模式5.1 代理模式5.1.1 代理模式介绍5.1.2 代理模式原理5.1.3 静态代理实现5.1.4 JDK动态代理5.1.4.1 JDK动态代理实现5.1.4.2 类是如何动态生成的5.1.4.3 代理类的调用过程 5.1.5 cglib动态代理5.1.5.1 cglib动态代理实现5.1.5.2 cglib代理流程 5.1.6 代理模式总结5.1.6.1 三种代理模式实现方式的对比5.1.6.2 代理模式优缺点5.1.6.2 代理模式使用场景 个人主页道友老李 欢迎加入社区道友老李的学习社区
第五章 结构型模式
我们已经学习过了设计模式中的创建型模式. 创建型模式主要解决对象的创建问题,封装复杂的创建过程,解耦对象的创建代码和使用代码.
单例模式用来创建全局唯一对象工厂模式用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象.建造者模式是用来创建复杂对象,可以通过设置不同的可选参数,定制化地创建不同的对象.原型模式针对创建成本比较大的对象,利用对已有对象进行复制的方式进行创建,以达到节省创建时间的目的.
从本节课开始我们来学习结构型设计模式, 结构型模式主要总结了一些类和对象组合在一起的经典结构,这些经典结构可以解决对应特定场景的问题.
一共包括七种代理模式、桥接模式、装饰者模式、适配器模式、门面(外观)模式、组合模式、和享元模式。
5.1 代理模式
5.1.1 代理模式介绍
在软件开发中,由于一些原因,客户端不想或不能直接访问一个对象,此时可以通过一个称为代理的第三者来实现间接访问.该方案对应的设计模式被称为代理模式.
代理模式(Proxy Design Pattern ) 原始定义是让你能够提供对象的替代品或其占位符。代理控制着对于原对象的访问并允许将请求提交给对象前后进行一些处理。
现实生活中的代理: 海外代购 软件开发中的代理 代理模式中引入了一个新的代理对象,代理对象在客户端对象和目标对象之间起到了中介的作用,它去掉客户不能看到的内容和服务或者增加客户需要的额外的新服务.
5.1.2 代理模式原理
代理Proxy模式分为三种角色
抽象主题Subject类 声明了真实主题和代理主题的共同接口,这样就可以保证任何使用真实主题的地方都可以使用代理主题,客户端一般针对抽象主题类进行编程。代理Proxy类 提供了与真实主题相同的接口其内部含有对真实主题的引用它可以在任何时候访问、控制或扩展真实主题的功能。真实主题Real Subject类 实现了抽象主题中的具体业务是代理对象所代表的真实对象是最终要引用的对象。 5.1.3 静态代理实现
这种代理方式需要代理对象和目标对象实现一样的接口。 优点可以在不修改目标对象的前提下扩展目标对象的功能。 缺点 冗余。由于代理对象要实现与目标对象一致的接口会产生过多的代理类。 不易维护。一旦接口增加方法目标对象与代理对象都要进行修改。 举例保存用户功能的静态代理实现 //接口类 IUserDao
public interface IUserDao {void save();
}
//目标对象UserDaoImpl
public class UserDaoImpl implements IUserDao {Overridepublic void save() {System.out.println(保存数据);}
}//静态代理对象UserDaoProxy 需要实现IUserDao接口
public class UserDaoProxy implements IUserDao {private IUserDao target;public UserDaoProxy(IUserDao target) {this.target target;}Overridepublic void save() {System.out.println(开启事务); //扩展额外功能target.save();System.out.println(提交事务);}
}//测试类
public class TestProxy {Testpublic void testStaticProxy(){//目标对象UserDaoImpl userDao new UserDaoImpl();//代理对象UserDaoProxy proxy new UserDaoProxy(userDao);proxy.save();}
}5.1.4 JDK动态代理
5.1.4.1 JDK动态代理实现
动态代理利用了JDK API,动态地在内存中构建代理对象,从而实现对目标对象的代理功能.动态代理又被称为JDK代理或接口代理.
静态代理与动态代理的区别:
静态代理在编译时就已经实现了,编译完成后代理类是一个实际的class文件动态代理是在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中.
JDK中生成代理对象主要涉及的类有
java.lang.reflect Proxy主要方法为
static Object newProxyInstance(ClassLoader loader, //指定当前目标对象使用类加载器Class?[] interfaces, //目标对象实现的接口的类型InvocationHandler h //事件处理器
)
//返回一个指定接口的代理类实例该接口可以将方法调用指派到指定的调用处理程序。java.lang.reflect InvocationHandler主要方法为 Object invoke(Object proxy, Method method, Object[] args)
// 在代理实例上处理方法调用并返回结果。举例保存用户功能的静态代理实现 /*** 代理工厂-动态生成代理对象/
public class ProxyFactory {private Object target; //维护一个目标对象public ProxyFactory(Object target) {this.target target;}//为目标对象生成代理对象public Object getProxyInstance(){//使用Proxy获取代理对象return Proxy.newProxyInstance(target.getClass().getClassLoader(), //目标类使用的类加载器target.getClass().getInterfaces(), //目标对象实现的接口类型new InvocationHandler(){ //事件处理器/* invoke方法参数说明* param proxy 代理对象* param method 对应于在代理对象上调用的接口方法Method实例* param args 代理对象调用接口方法时传递的实际参数* return: java.lang.Object 返回目标对象方法的返回值,没有返回值就返回null*/Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(开启事务);//执行目标对象方法method.invoke(target, args);System.out.println(提交事务);return null;}});}}//测试
public static void main(String[] args) {IUserDao target new UserDaoImpl();System.out.println(target.getClass());//目标对象信息IUserDao proxy (IUserDao) new ProxyFactory(target).getProxyInstance();System.out.println(proxy.getClass()); //输出代理对象信息proxy.save(); //执行代理方法
}5.1.4.2 类是如何动态生成的
Java虚拟机类加载过程主要分为五个阶段加载、验证、准备、解析、初始化。其中加载阶段需要完成以下3件事情
通过一个类的全限定名来获取定义此类的二进制字节流将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构在内存中生成一个代表这个类的 java.lang.Class 对象作为方法区这个类的各种数据访问入口
由于虚拟机规范对这3点要求并不具体所以实际的实现是非常灵活的关于第1点获取类的二进制字节流class字节码就有很多途径 从本地获取 从网络中获取 运行时计算生成这种场景使用最多的是动态代理技术在 java.lang.reflect.Proxy 类中就是用了 ProxyGenerator.generateProxyClass 来为特定接口生成形式为 \(Proxy 的代理类的二进制字节流 所以动态代理就是想办法根据接口或目标对象计算出代理类的字节码然后再加载到JVM中使用
5.1.4.3 代理类的调用过程
我们通过借用阿里巴巴的一款线上监控诊断产品 Arthas(阿尔萨斯) ,对动态生成的代理类代码进行查看。
代理类代码如下:
package com.sun.proxy;import com.mashibing.proxy.example01.IUserDao;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;public final class \)Proxy0
extends Proxy
implements IUserDao {private static Method m1;private static Method m3;private static Method m2;private static Method m0;public \(Proxy0(InvocationHandler invocationHandler) {super(invocationHandler);}static {try {m1 Class.forName(java.lang.Object).getMethod(equals, Class.forName(java.lang.Object));m3 Class.forName(com.mashibing.proxy.example01.IUserDao).getMethod(save, new Class[0]);m2 Class.forName(java.lang.Object).getMethod(toString, new Class[0]);m0 Class.forName(java.lang.Object).getMethod(hashCode, new Class[0]);return;}catch (NoSuchMethodException noSuchMethodException) {throw new NoSuchMethodError(noSuchMethodException.getMessage());}catch (ClassNotFoundException classNotFoundException) {throw new NoClassDefFoundError(classNotFoundException.getMessage());}}public final boolean equals(Object object) {try {return (Boolean)this.h.invoke(this, m1, new Object[]{object});}catch (Error | RuntimeException throwable) {throw throwable;}catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}public final String toString() {try {return (String)this.h.invoke(this, m2, null);}catch (Error | RuntimeException throwable) {throw throwable;}catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}public final int hashCode() {try {return (Integer)this.h.invoke(this, m0, null);}catch (Error | RuntimeException throwable) {throw throwable;}catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}public final void save() {try {this.h.invoke(this, m3, null);return;}catch (Error | RuntimeException throwable) {throw throwable;}catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}
}简化后的代码
package com.sun.proxy;import com.mashibing.proxy.example01.IUserDao;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;public final class \)Proxy0
extends Proxy
implements IUserDao {private static Method m3;public $Proxy0(InvocationHandler invocationHandler) {super(invocationHandler);}static {try {m3 Class.forName(com.mashibing.proxy.example01.IUserDao).getMethod(save, new Class[0]);return;}}public final void save() {try {this.h.invoke(this, m3, null);return;}}
}动态代理类对象 继承了 Proxy 类并且实现了被代理的所有接口以及equals、hashCode、toString等方法 代理类的构造函数参数是InvocationHandler实例Proxy.newInstance方法就是通过这个构造函数来创建代理实例的 类和所有方法都被 public final 修饰所以代理类只可被使用不可以再被继承 每个方法都有一个 Method 对象来描述Method 对象在static静态代码块中创建以 m 数字 的格式命名 调用方法的时候通过 this.h.invoke(this, m3, null)); 实际上 h.invoke就是在调用ProxyFactory中我们重写的invoke方法 Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(开启事务);//执行目标对象方法method.invoke(target, args);System.out.println(提交事务);return null;
}5.1.5 cglib动态代理
5.1.5.1 cglib动态代理实现
cglib (Code Generation Library ) 是一个第三方代码生成类库运行时在内存中动态生成一个子类对象从而实现对目标对象功能的扩展。cglib 为没有实现接口的类提供代理为JDK的动态代理提供了很好的补充。 最底层是字节码ASM是操作字节码的工具cglib基于ASM字节码工具操作字节码即动态生成代理对方法进行增强SpringAOP基于cglib进行封装实现cglib方式的动态代理
使用cglib 需要引入cglib 的jar包如果你已经有spring-core的jar包则无需引入因为spring中包含了cglib 。
cglib 的Maven坐标
dependencygroupIdcglib/groupIdartifactIdcglib/artifactIdversion3.2.5/version
/dependency示例代码
目标类
public class UserServiceImpl {public ListUser findUserList(){return Collections.singletonList(new User(tom,18));}
}public class User {private String name;private int age;…..
}cglib代理类需要实现MethodInterceptor接口并指定代理目标类target
public class UserLogProxy implements MethodInterceptor {private Object target;public UserLogProxy(Object target) {this.target target;}public Object getLogProxy(){//增强器类,用来创建动态代理类Enhancer en new Enhancer();//设置代理类的父类字节码对象en.setSuperclass(target.getClass());//设置回调: 对于代理类上所有的方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦截en.setCallback(this);//创建动态代理对象并返回return en.create();}/** 实现回调方法* param o 代理对象* param method 目标对象中的方法的Method实例* param args 实际参数* param methodProxy 代理对象中的方法的method实例* return: java.lang.Object*/Overridepublic Object intercept(Object o, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {Calendar calendar Calendar.getInstance();SimpleDateFormat formatter new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);System.out.println(formatter.format(calendar.getTime()) [ method.getName() ] 查询用户信息…]);Object result methodProxy.invokeSuper(o, args);return result;}
}public class Client {public static void main(String[] args) {//目标对象UserServiceImpl userService new UserServiceImpl();System.out.println(userService.getClass());//代理对象UserServiceImpl proxy (UserServiceImpl) new UserLogProxy(userService).getLogProxy();System.out.println(proxy.getClass());ListUser userList proxy.findUserList();System.out.println(用户信息: userList);}
}5.1.5.2 cglib代理流程 5.1.6 代理模式总结
5.1.6.1 三种代理模式实现方式的对比 jdk代理和CGLIB代理 使用CGLib实现动态代理CGLib底层采用ASM字节码生成框架使用字节码技术生成代理类在JDK1.6之前比使用Java反射效率要高。唯一需要注意的是CGLib不能对声明为final的类或者方法进行代理因为CGLib原理是动态生成被代理类的子类。 在JDK1.6、JDK1.7、JDK1.8逐步对JDK动态代理优化之后在调用次数较少的情况下JDK代理效率高于CGLib代理效率只有当进行大量调用的时候JDK1.6和JDK1.7比CGLib代理效率低一点但是到JDK1.8的时候JDK代理效率高于CGLib代理。所以如果有接口使用JDK动态代理如果没有接口使用CGLIB代理。 动态代理和静态代理 动态代理与静态代理相比较最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理InvocationHandler.invoke。这样在接口方法数量比较多的时候我们可以进行灵活处理而不需要像静态代理那样每一个方法进行中转。 如果接口增加一个方法静态代理模式除了所有实现类需要实现这个方法外所有代理类也需要实现此方法。增加了代码维护的复杂度。而动态代理不会出现该问题
5.1.6.2 代理模式优缺点
优点
代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用代理对象可以扩展目标对象的功能代理模式能将客户端与目标对象分离在一定程度上降低了系统的耦合度
缺点
增加了系统的复杂度
5.1.6.2 代理模式使用场景 功能增强 当需要对一个对象的访问提供一些额外操作时,可以使用代理模式 远程Remote代理 实际上RPC 框架也可以看作一种代理模式GoF 的《设计模式》一书中把它称作远程代理。通过远程代理将网络通信、数据编解码等细节隐藏起来。客户端在使用 RPC 服务的时候就像使用本地函数一样无需了解跟服务器交互的细节。除此之外RPC 服务的开发者也只需要开发业务逻辑就像开发本地使用的函数一样不需要关注跟客户端的交互细节。 防火墙Firewall代理 当你将浏览器配置成使用代理功能时防火墙就将你的浏览器的请求转给互联网当互联网返回响应时代理服务器再把它转给你的浏览器。 保护Protect or Access代理 控制对一个对象的访问如果需要可以给不同的用户提供不同级别的使用权限。
相关文章
-
wap网站推荐wordpress速度慢设置
wap网站推荐wordpress速度慢设置
- 站长
- 2026年02月18日
-
wap网站搜索公关公司职级
wap网站搜索公关公司职级
- 站长
- 2026年02月18日
-
wap网站设计规范中国建设银行亚洲网站
wap网站设计规范中国建设银行亚洲网站
- 站长
- 2026年02月18日
-
wap网站制作app宝塔ssl wordpress
wap网站制作app宝塔ssl wordpress
- 站长
- 2026年02月18日
-
wap微信网站模板蓝色网站导航
wap微信网站模板蓝色网站导航
- 站长
- 2026年02月18日
-
wap站开发做网站ppt
wap站开发做网站ppt
- 站长
- 2026年02月18日
