long startTime = System.currentTimeMillis();
Boolean login = super.login(username, password);
long endTime = System.currentTimeMillis();
System.out.println(“login time : " + (endTime - startTime) +” ms" );
return login;
}
}
package com.ymy.proxy;
/**
-
@ProjectName: demo
-
@Package: com.ymy.proxy
-
@ClassName: Test
-
@Author: 流星007
-
@Description: test
-
csdn:https://blog.csdn.net/qq_33220089
-
今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523
-
@Date: 2020/8/29 15:15
-
@Version: 1.0
*/
public class Test {
public static void main(String[] args) {
UserServiceProxy userServiceProxy = new UserServiceProxy();
Boolean login = userServiceProxy.login(“zhgnsan”, “123456”);
System.out.println("login result : " +login);
}
}
username:zhgnsan
password:123456
login time : 0 ms
login result : true
Process finished with exit code 0
UserService:被代理类,UserServiceProxy:代理类,请求先经过代理类,然后由代理类去操作被代理类,最终记录时间,这样就可以在不改变原来代码的情况下新增功能,是不是很方便。
刚刚讲解了怎么利用继承实现一个静态代理模式,那现在再来讲解另外一种基于组合模式实现静态代理,改造代码开始
package com.ymy.proxy;
/**
-
@ProjectName: demo
-
@Package: com.ymy.proxy
-
@ClassName: IUserService
-
@Author: 流星007
-
@Description: user interface
-
csdn:https://blog.csdn.net/qq_33220089
-
今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523
-
@Date: 2020/8/29 15:26
-
@Version: 1.0
*/
public interface IUserService {
Boolean login(String username,String password);
}
package com.ymy.proxy;
/**
-
@ProjectName: demo
-
@Package: com.ymy.proxy
-
@ClassName: UserService
-
@Author: 流星007
-
@Description: user login or register
-
csdn:https://blog.csdn.net/qq_33220089
-
今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523
-
@Date: 2020/8/29 15:10
-
@Version: 1.0
*/
public class UserService implements IUserService{
/**
-
login in
-
@param username
-
@param password
*/
@Override
public Boolean login(String username,String password){
System.out.println(“username:”+username);
System.out.println(“password:”+password);
return true;
}
}
package com.ymy.proxy;
/**
-
@ProjectName: demo
-
@Package: com.ymy.proxy
-
@ClassName: UserServiceProxy
-
@Author: 流星007
-
@Description: user proxy
-
csdn:https://blog.csdn.net/qq_33220089
-
今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523
-
@Date: 2020/8/29 15:29
-
@Version: 1.0
*/
public class UserServiceProxy implements IUserService{
private UserService userService;
public UserServiceProxy(UserService userService) {
this.userService = userService;
}
@Override
public Boolean login(String username, String password) {
long startTime = System.currentTimeMillis();
Boolean login = userService.login(username, password);
long endTime = System.currentTimeMillis();
System.out.println(“login time : " + (endTime - startTime) +” ms" );
return login;
}
}
package com.ymy.proxy;
/**
-
@ProjectName: demo
-
@Package: com.ymy.proxy
-
@ClassName: Test
-
@Author: 流星007
-
@Description: test
-
csdn:https://blog.csdn.net/qq_33220089
-
今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523
-
@Date: 2020/8/29 15:15
-
@Version: 1.0
*/
public class Test {
public static void main(String[] args) {
UserServiceProxy userServiceProxy = new UserServiceProxy(new UserService());
Boolean login = userServiceProxy.login(“zhgnsan”, “123456”);
System.out.println("login result : " +login);
}
}
这就是基于组合模式实现的静态代理,代理类和被代理类同时实现一个IUserService接口,代理类中的login方法去调用被代理类中的login方法,这样需要稍微改动一下被代理类,让他们去实现同一个接口。
========================================================================
静态代理的实现方式相信大家也应该知道怎么实现了,那什么时候实现组合,什么时候使用继承呢?不知道大家有没有听过这么一句话:组合优于继承;能使用组合就少使用继承,原因是继承的层数过大时维护和扩展会非常难受,但是也不绝对,相对于代理模式而言,如果被代理的类来源于第三方,你无法改动原类,那么继承将是一个不错的原则,一般情况下,我还是推荐组合的这种方式。
===============================
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享
====================================
静态代理是说完了,还有一种代理模式不知道大家听过没有,那就是动态代理模式,如果熟悉java aop的都应该对java的动态代理不会陌生,那我们现在来讲讲什么是动态代理。
不知道大家思考过一个问题没有,你们觉得静态代理有什么缺点吗?
可能大家想到了,如果被代理的类过多,成千上百的话,代理类也要成千上百,大大增加了程序员的工作量,他们都是差不多的一个模板,难道就不能只写一次,符合所有的被代理类吗?
当然可以,这个时候动态代理就出现了,动态代理:就是我们不需要在程序运行前为被代理类创建代理类,而是在程序运行中,动态的创建代理类,然后使用这些动态生成的代理类替代原始类,是不是就省去了大量的编码时间?那如何实现呢?
下面请看我表演
package com.ymy.proxy;
/**
-
@ProjectName: demo
-
@Package: com.ymy.proxy
-
@ClassName: IUserService
-
@Author: 流星007
-
@Description: user interface
-
csdn:https://blog.csdn.net/qq_33220089
-
今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523
-
@Date: 2020/8/29 15:26
-
@Version: 1.0
*/
public interface IUserService {
Boolean login(String username,String password);
}
package com.ymy.proxy;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.cglib.proxy.Proxy;
import java.lang.reflect.Method;
/**
-
@ProjectName: demo
-
@Package: com.ymy.proxy
-
@ClassName: dynamicUserUserProxy
-
@Author: 流星007
-
@Description: dynamic User proxy
-
csdn:https://blog.csdn.net/qq_33220089
-
今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523
-
@Date: 2020/8/30 13:33
-
@Version: 1.0
*/
public class DynamicUserUserProxy {
public Object createProxy(Object object) {
Class[] interfaces = object.getClass().getInterfaces();
DynamicProxyHandler handler = new DynamicProxyHandler(object);
return Proxy.newProxyInstance(object.getClass().getClassLoader(), interfaces, handler);
}
private class DynamicProxyHandler implements InvocationHandler {
private Object object;
public DynamicProxyHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = method.invoke(object, args);
long endTime = System.currentTimeMillis();
System.out.println(“login time : " + (endTime - startTime) +” ms" );
return result;
}
}
}
package com.ymy.proxy;
/**
-
@ProjectName: demo
-
@Package: com.ymy.proxy
-
@ClassName: DynamicTest
-
@Author: 流星007
-
@Description: Dynamic Test
-
csdn:https://blog.csdn.net/qq_33220089
-
今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523
-
@Date: 2020/8/30 13:36
-
@Version: 1.0
*/
public class DynamicTest {
public static void main(String[] args) {
DynamicUserUserProxy proxy = new DynamicUserUserProxy();
IUserService userService = (IUserService) proxy.createProxy(new UserService());
Boolean login = userService.login(“zhangsan”, “123456”);
System.out.println(“login result :” +login);
}
}
username:zhangsan
password:123456
login time : 0 ms
login result :true
Process finished with exit code 0
我这里实现动态代理是基于cglib,由静态代理改成动态代理之后是不是觉得干净多了,如果后续还有类需要代理,就不需要在创建代理类了,让程序在运行中自己创建,简直不要太爽。
=======================================================================
1.日志、鉴权、限流、统计等物业功能的开发。
2.rpc远程调用。
3.一个类需要做扩展功能的时候。
=================================================================
什么是代理模式?,就是在不改变原类的情况下新增新的功能,比如日志、流量监控、请求耗时等等操作都可以通过代理模式来解决。
代理模式分为静态代理和动态代理,静态代理可以通过继承和组合实现,动态代理可以通过cglib和jdk自带的动态代理实现,如果在日常开发过程中,你想要做一些扩展功能,比如:日志、鉴权等,那么就可以考虑一下代理模式哦。
推荐文章: