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.comAccess Denied:qq.com
不能访问娱乐性网站 , 但是可以用 360 搜索 , SO 靠谱 , 哈哈静态代理类优缺点优点:在不修改目标对象的前提下 , 可以通过代理对象对目标对象功能扩展
代理使客户端不需要知道实现类是什么 , 怎么做的 , 而客户端只需知道代理即可(解耦合) , 对于如上的客户端代码 , RealInterner() 可以应用工厂将它隐藏 。
缺点:
- 代理类和委托类实现了相同的接口 , 代理类通过委托类实现了相同的方法 。这样就出现了大量的代码重复 。如果接口增加一个方法 , 除了所有实现类需要实现这个方法外 , 所有代理类也需要实现此方法 。增加了代码维护的复杂度 。
- 代理对象只服务于一种类型的对象 , 如果要服务多类型的对象 。势必要为每一种对象都进行代理 , 静态代理在程序规模稍大时就无法胜任了 。
JDK原生动态代理
- 代理对象 , 不需要实现接口 , 但是目标对象要实现接口 , 否则不能用动态代理
- 代理对象的生成 , 是通过 JDK 的 API(反射机制) , 动态的在内存中构建代理对象
java.lang.reflect.InvocationHandler 接口和 java.lang.reflect.Proxy 类的支持
Coding1、网络接口不变
public interface Internet { void connectTo(String serverHost) throws Exception;}
2、真正的网络连接 , 也不会改变public class RealInternet implements Internet{ @Override public 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() { @Override public 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 List<String> bannedSites; static { bannedSites = new ArrayList<String>(); bannedSites.add("bilibili.com"); bannedSites.add("youtube.com"); bannedSites.add("weibo.com"); bannedSites.add("qq.com"); }}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 如何在面试中解释各种机器学习模型
- 求职|思维策略:一项目完胜大多数所谓面试神技的策略(上)
- Spring Boot 上传图片完整示例
- SpringBoot中获取微信用户信息从未如此简单
- Spring Boot配置文件yml格式详解
- 超全、超详的Spring Boot配置讲解笔记
- 面试|我月薪5千,面试如何谈到1万?
- Java包装类与基本类型区别与应用,解析面试题
- 面试官:先来简单聊一下SQL Join,看你对数据了解的怎么样
- 谷歌面试问题50%需要用递归:理解递归算法的本质这篇够不够?