您现在的位置是:主页 > news > 网站被做跳转怎么办/南宁seo手段
网站被做跳转怎么办/南宁seo手段
admin2025/5/11 21:13:42【news】
简介网站被做跳转怎么办,南宁seo手段,什么公司网站建设做的好,网站模板修改教程哈喽,大家好! 代理模式相信大家经常听说,在设计模式中相对而言是比较难理解的。这次小编来给大家通俗的介绍介绍。 1.什么是代理模式 Provide a surrogate or placeholder for another object to control access to it. Proxy Pattern:为…
哈喽,大家好!
代理模式相信大家经常听说,在设计模式中相对而言是比较难理解的。这次小编来给大家通俗的介绍介绍。
1.什么是代理模式
Provide a surrogate or placeholder for another object to control access to it.
Proxy Pattern:为其他对象提供一种代理以控制对这个对象的访问。
说人话:在不改变原始类(或叫被代理类)代码的情况下,通过引入代理类来给原始类附加功能,比如Spring AOP。
2.代理模式定义
①Subject
抽象主题角色,可以是抽象类,可以是接口,是一个最普通的业务类定义,无特殊要求。
②RealSubject
真实主题角色,也叫被代理角色,是业务逻辑的具体执行者。
③Proxy
代理主题角色,也叫代理类,它负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现,并在真实主题角色处理前后做一些预处理或善后工作。
通用代码如下:
/*** 抽象主题类*/
public interface Subject {void doSomething();
}
/*** 真实主题角色*/
public class RealSubject implements Subject{@Overridepublic void doSomething() {//TODO 具体执行的事}
}
/*** 代理主题角色*/
public class Proxy implements Subject{//要代理的具体实现类private Subject realSubject;public Proxy(Subject realSubject){this.realSubject = realSubject;}@Overridepublic void doSomething() {this.before();realSubject.doSomething();this.after();}// 预处理private void before(){// TODO}// 善后处理private void after(){// TODO}
}
3.代理模式的两种实现
比如用代理模式实现统计某个接口的耗时。
3.1 静态代理
①基于接口编程
抽象主题类:
public interface IUserController {// 登录String login(String username,String password);// 注册String register(String username,String password);
}
具体主题类:
public class UserController implements IUserController{@Overridepublic String login(String username, String password) {// TODO 登录逻辑return null;}@Overridepublic String register(String username, String password) {// TODO 注册逻辑return null;}
}
代理主题类:
public class UserControllerProxy implements IUserController{private IUserController userController;public UserControllerProxy(IUserController userController){this.userController = userController;}@Overridepublic String login(String username, String password) {long startTime = System.currentTimeMillis();// 登录逻辑userController.login("username","password");long endTime = System.currentTimeMillis();long responseTime = endTime - startTime;System.out.println("接口响应时间:"+responseTime);return null;}@Overridepublic String register(String username, String password) {long startTime = System.currentTimeMillis();// 注册逻辑userController.register("username","password");long endTime = System.currentTimeMillis();long responseTime = endTime - startTime;System.out.println("接口响应时间:"+responseTime);return null;}
}
测试:
因为原始类 UserController 和代理类 UserControllerProxy 实现相同的接口,是基于接口而非实现编程,将UserController类对象替换为UserControllerProxy类对象,不需要改动太多代码
public class StaticProxyTest {public static void main(String[] args) {IUserController userController = new UserControllerProxy(new UserController());userController.login("username","password");userController.register("username","password");}
}
在上面的代码中,代理类和具体主题类需要实现相同的接口,假如具体主题类没有实现接口,并且不是我们开发维护的(比如来自第三方接口),我们要统计这个第三方接口的耗时,那应该如何实现代理模式呢?
②基于继承
继承具体主题类,然后扩展其方法即可,直接看代码。
public class UserControllerProxy extends UserController {@Overridepublic String login(String username, String password) {long startTime = System.currentTimeMillis();// 登录逻辑super.login("username","password");long endTime = System.currentTimeMillis();long responseTime = endTime - startTime;System.out.println("接口响应时间:"+responseTime);return null;}@Overridepublic String register(String username, String password) {long startTime = System.currentTimeMillis();// 注册逻辑super.register("username","password");long endTime = System.currentTimeMillis();long responseTime = endTime - startTime;System.out.println("接口响应时间:"+responseTime);return null;}
}
3.2 动态代理
在上面的例子中,有两个问题:
①我们需要在代理类中,将具体主题类中的所有的方法,都重新实现一遍,并且为每个方法都附加相似的代码逻辑,如果方法很多,重复代码也会很多。
②如果要添加的附加功能的类有不止一个,我们需要针对每个类都创建一个代理类。
那该如何解决上面的问题呢?答案就是动态代理(Dynamic Proxy)。
动态代理:不事先为每个原始类编写代理类,而是在运行的时候,动态地创建原始类对应的代理类,然后在系统中用代理类替换掉原始类。
JDK动态代理:
public class DynamicProxyHandler implements InvocationHandler {private Object target;public DynamicProxyHandler(Object target){this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {long startTime = System.currentTimeMillis();Object result = method.invoke(this.target, args);long endTime = System.currentTimeMillis();long responseTime = endTime - startTime;System.out.println("接口响应时间:"+responseTime);return result;}
}
测试:
public class DynamicProxyTest {public static void main(String[] args) {// 1、创建具体主题类IUserController userController = new UserController();// 2、创建 HandlerDynamicProxyHandler proxyHandler = new DynamicProxyHandler(userController);// 3、动态产生代理类IUserController o = (IUserController)Proxy.newProxyInstance(userController.getClass().getClassLoader(),userController.getClass().getInterfaces(),proxyHandler);o.login("username","password");o.register("username","password");}
}
这是 JDK 动态代理,利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理,代理对象是在程序运行时产生的,而不是编译期,要求是具体主题类必须实现接口。
另外一种方式是 Cglib 动态代理。CGLIB(Code Generation Library)是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成,也就是通过修改字节码生成子类来处理。
Cglib 动态代理:
public class UserController{public String login(String username, String password) {// TODO 登录逻辑System.out.println("登录");return null;}public String register(String username, String password) {// TODO 注册逻辑System.out.println("注册");return null;}
}
注意:真实主题类是没有实现接口的。
public class CglibDynamicProxy implements MethodInterceptor {private Object target;public CglibDynamicProxy(Object target){this.target = target;}// 给目标创建代理对象public Object newProxyInstance(){// 1.工具类Enhancer enhancer = new Enhancer();// 2.设置父类enhancer.setSuperclass(target.getClass());// 3.设置回调函数enhancer.setCallback(this);// 4.创建子类(代理对象)return enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {long startTime = System.currentTimeMillis();Object result = method.invoke(this.target, args);long endTime = System.currentTimeMillis();long responseTime = endTime - startTime;System.out.println("接口响应时间:"+responseTime);return result;}
}
测试:
public class CglibDynamicProxyTest {public static void main(String[] args) {UserController userController = new UserController();CglibDynamicProxy cglibDynamicProxy = new CglibDynamicProxy(userController);UserController o = (UserController)cglibDynamicProxy.newProxyInstance();o.login("username","password");o.register("username","password");}
}
4.代理模式优点
①职责清晰
真实的角色就是实现实际的业务逻辑, 不用关心其他非本职责的事务, 通过后期的代理完成一件事务, 附带的结果就是编程简洁清晰。
②高扩展性
具体主题角色是随时都会发生变化的, 只要它实现了接口, 甭管它如何变化,代理类完全都可以在不做任何修改的情况下使用。
5.代理模式应用场景
①业务系统的非功能性需求开发
这是最常用的一个场景。比如:监控、统计、鉴权、限流、事务、幂等、日志。我们将这些附加功能与业务功能解耦,放到代理类中统一处理,让程序员只需要关注业务方面的开发。
典型例子就是 SpringAOP。
②RPC
RPC(远程代理) 框架也可以看作一种代理模式,通过远程代理,将网络通信、数据编解码等细节隐藏起来。客户端在使用 RPC 服务的时候,就像使用本地函数一样,无需了解跟服务器交互的细节。除此之外,RPC 服务的开发者也只需要开发业务逻辑,就像开发本地使用的函数一样,不需要关注跟客户端的交互细节。