body { margin: 0 auto; font: 13px / 1 Helvetica, Arial, sans-serif; color: rgba(68, 68, 68, 1); padding: 5px }
h1, h2, h3, h4 { color: rgba(17, 17, 17, 1); font-weight: 400 }
h1, h2, h3, h4, h5, p { margin-bottom: 16px; padding: 0 }
h1 { font-size: 28px }
h2 { font-size: 22px; margin: 20px 0 6px }
h3 { font-size: 21px }
h4 { font-size: 18px }
h5 { font-size: 16px }
a { color: rgba(0, 153, 255, 1); margin: 0; padding: 0; vertical-align: baseline }
a:link, a:visited { text-decoration: none }
a:hover { text-decoration: underline }
ul, ol { padding: 0; margin: 0 }
li { line-height: 24px; margin-left: 30px }
li ul, li ul { margin-left: 24px }
ul, ol { font-size: 14px; line-height: 20px; max-width: 98% }
p { font-size: 14px; line-height: 20px; max-width: 98%; margin-top: 3px }
pre { padding: 0 4px; max-width: 98%; white-space: pre; word-wrap: normal; overflow: auto; font-family: Consolas, Monaco, Andale Mono, monospace; line-height: 1.5; font-size: 13px; border: 1px solid rgba(221, 221, 221, 1); background-color: rgba(247, 247, 247, 1); border-radius: 3px }
code { font-family: Consolas, Monaco, Andale Mono, monospace; line-height: 1.5; font-size: 13px; border: 1px solid rgba(221, 221, 221, 1); background-color: rgba(247, 247, 247, 1); border-radius: 3px }
code pref { color: rgba(255, 0, 0, 1) }
pre code { border: 0 }
aside { display: block; float: right; width: 390px }
blockquote { border-left: 0.5em solid rgba(64, 170, 83, 1); padding: 0 2em; margin-left: 0; max-width: 98% }
blockquote cite { font-size: 14px; line-height: 20px; color: rgba(191, 191, 191, 1) }
blockquote cite:before { content: "— " }
blockquote p { color: rgba(102, 102, 102, 1); max-width: 98% }
hr { height: 1px; border-top: 1px dashed rgba(0, 102, 204, 1); border-right: none; border-bottom: none; border-left: none }
button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle }
button, input { line-height: normal; *overflow: visible }
{ border: 0; padding: 0 }
button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button }
input[type="checkbox"], input[type="radio"] { cursor: pointer }
input:not([type="image"]), textarea { -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box }
input[type="search"] { -webkit-appearance: textfield; -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box }
{ -webkit-appearance: none }
label, input, select, textarea { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; font-weight: normal; line-height: normal; margin-bottom: 18px }
input[type="checkbox"], input[type="radio"] { cursor: pointer; margin-bottom: 0 }
input[type="text"], input[type="password"], textarea, select { display: inline-block; width: 210px; padding: 4px; font-size: 13px; font-weight: normal; line-height: 18px; height: 18px; color: rgba(128, 128, 128, 1); border: 1px solid rgba(204, 204, 204, 1); -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px }
select, input[type="file"] { height: 27px; line-height: 27px }
textarea { height: auto }
{ color: rgba(191, 191, 191, 1) }
{ color: rgba(191, 191, 191, 1) }
input[type="text"], input[type="password"], select, textarea { -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; -moz-transition: border linear 0.2s, box-shadow linear 0.2s; transition: border 0.2s linear, box-shadow 0.2s linear; -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1) }
input[type="text"]:focus, input[type="password"]:focus, textarea:focus { outline: none; border-color: rgba(82, 168, 236, 0.8); -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6) }
button { display: inline-block; padding: 4px 14px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; line-height: 18px; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); background-color: rgba(0, 100, 205, 1); background-repeat: repeat-x; color: rgba(255, 255, 255, 1); text-shadow: 0 -1px rgba(0, 0, 0, 0.25); border-top: 1px solid rgba(0, 0, 0, 0.1); border-right: 1px solid rgba(0, 0, 0, 0.1); border-bottom: 1px solid rgba(0, 0, 0, 0.25); border-left: 1px solid rgba(0, 0, 0, 0.1); -webkit-transition: 0.1s linear all; -moz-transition: 0.1s linear all; transition: all 0.1s linear }
button:hover { color: rgba(255, 255, 255, 1); background-position: 0 -15px; text-decoration: none }
button:active { -webkit-box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05) }
{ padding: 0; border: 0 }
table { border-spacing: 0; border: 1px solid rgba(204, 204, 204, 1) }
td, th { border: 1px solid rgba(204, 204, 204, 1); padding: 5px }
pre .literal, pre .comment, pre .template_comment, pre .diff .header, pre .javadoc { color: rgba(0, 128, 0, 1) }
pre .keyword, pre .css .rule .keyword, pre .winutils, pre .javascript .title, pre .nginx .title, pre .subst, pre .request, pre .status { color: rgba(0, 0, 255, 1); font-weight: bold }
pre .number, pre .hexcolor, pre .python .decorator, pre .ruby .constant { color: rgba(0, 0, 255, 1) }
pre .string, pre .tag .value, pre .phpdoc, pre .tex .formula { color: rgba(221, 17, 68, 1) }
pre .title, pre .id { color: rgba(153, 0, 0, 1); font-weight: bold }
pre .javascript .title, pre .lisp .title, pre .clojure .title, pre .subst { font-weight: normal }
pre .class .title, pre .haskell .type, pre .vhdl .literal, pre .tex .command { color: rgba(68, 85, 136, 1); font-weight: bold }
pre .tag, pre .tag .title, pre .rules .property, pre .django .tag .keyword { color: rgba(0, 0, 128, 1); font-weight: normal }
pre .attribute, pre .variable, pre .lisp .body { color: rgba(0, 128, 128, 1) }
pre .regexp { color: rgba(0, 153, 38, 1) }
pre .class { color: rgba(68, 85, 136, 1); font-weight: bold }
pre .symbol, pre .ruby .symbol .string, pre .lisp .keyword, pre .tex .special, pre .prompt { color: rgba(153, 0, 115, 1) }
pre .built_in, pre .lisp .title, pre .clojure .built_in { color: rgba(0, 134, 179, 1) }
pre .preprocessor, pre .pi, pre .doctype, pre .shebang, pre .cdata { color: rgba(153, 153, 153, 1); font-weight: bold }
pre .deletion { background: rgba(255, 221, 221, 1) }
pre .addition { background: rgba(221, 255, 221, 1) }
pre .diff .change { background: rgba(0, 134, 179, 1) }
pre .chunk { color: rgba(170, 170, 170, 1) }
pre .markdown .header { color: rgba(136, 0, 0, 1); font-weight: bold }
pre .markdown .blockquote { color: rgba(136, 136, 136, 1) }
pre .markdown .link_label { color: rgba(136, 136, 255, 1) }
pre .markdown .strong { font-weight: bold }
pre .markdown .emphasis { font-style: italic }
pref { color: rgba(255, 0, 0, 1) }

The role of proxy, application scenarios, and implementation in Java programs.

代理是程序设计和开发时频繁使用的技术,可以提高程序灵活性和可扩展性。

1 代理作用

  1. 在不修改原代码的基础上,扩展和增强实现;
  2. 代码解耦,在代理中通过参数可以判断真实类,做出不同的响应或调用,灵活方便;
  3. 隐藏部分实现过程和细节。

2 应用场景

ICar接口类,有一个drive方法,传入speed(速度)行驶,现在已经有Mitsubishi(三菱车)和Bwm(宝马车)实现了接口,随着业务发展,可能有更多的车加入;程序稳健运行一段时间后,针对不同的车发现了不同的问题需要处理,比如Mitsubishi车drive前必须检查和保证冷却液充足;Bwm车drive前必须检查和保证机油充足;由于改写ICar接口可能影响到其它的车;如果有很多的车要处理,更改实现类可能需要花费大量时间,此时可以通过代理类扩展和增强。

在代理类(CarProxy)中通过carCheck方法实现对不同汽车检查,检查通过后drive汽车,从而实现对原有代码增强。

3 代理的实现

3.1 静态代理

静态代理的思想:代理类和其它汽车类一样实现接口类,在重写方法里实现扩展或增强,并调要汽车类实现。

//宝马汽车实现类
class Bwm implements ICar {
public void drive(int speed) {
System.out.println("Bwm drive with speed:"+speed);
}
//三菱汽车实现类
class Mitsubishi implements ICar {
public void drive(int speed) {
System.out.println("Mitsubishi drive with speed:"+speed);
} //汽车代理类
public class CarProxy implements ICar {
private ICar carTarget;
public CarProxy(ICar carTarget){
this.carTarget=carTarget;
}
// 车辆检查
private boolean carCheck() {
if(this.carTarget instanceof Mitsubishi){ //判断汽车类型
System.out.println("Mitsubishi 检查冷却液完成。");
return true;
}else if(this.carTarget instanceof Bwm){
System.out.println("Bwm 检查机油完成。");
return true;
}else{
System.out.println("该车不需要检查。");
return true;
}
} /** 驾驶
* @param speed 速度
*/
public void drive(int speed) {
if(carCheck()){ //检查通过后drive
carTarget.drive(speed); //调用汽车类
}
}
}

在CarProxy代理类中,增加了对不同汽车的检查方法(carCheck),当汽车检查通过后调用(drive)方法驾驶汽车。这样代理类便实现了对三菱和宝马车的扩展,调用时传入ICar实现类对象;

new CarProxy(new Mitsubishi()).drive(80); //drive 三菱车
new CarProxy(new Bwm()).drive(100); //drive 宝马车

运行输出;

Mitsubishi 检查冷却液完成。
Mitsubishi drive with speed:80
Bwm 检查机油完成。
Bwm drive with speed:100

3.1.1 缺点

接口类变化会影响实现类和代理类;比如方法修改返回值、参数类型、增加方法,实现类和代理类都需要修改。

3.2 动态代理

Java 提供(java.lang.reflect.InvocationHandler)代理实例接口,代理类实现该接口关联调用处理程序的方法(invoke),当在代理实例调用方法时,方法调用被编码(encoded)并分配给其调用处理程序的方法。

public class DynamicProxy implements InvocationHandler{
Object carTarget; //车辆检查
private boolean carCheck() {
if(this.carTarget instanceof Mitsubishi){
System.out.println("Mitsubishi 检查冷却液完成。");
return true;
}else if(this.carTarget instanceof Bwm){
System.out.println("Bwm 检查机油完成。");
return true;
}else{
System.out.println("该车不需要检查。");
return true;
}
} //创建代理类实例
Object crateProxyInstance(Object carTarget) {
this.carTarget = carTarget;
return Proxy.newProxyInstance(carTarget.getClass().getClassLoader(),
carTarget.getClass().getInterfaces(),this);
} @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(carCheck()){//汽车检查通过后drive
return method.invoke(carTarget,args);
}
return null;
}
}

除了crateProxyInstance 和 invoke 方法外,对三菱和宝马车的扩展(车辆检查)与静态类相同。调用时同样传入ICar实现类对象。

((ICar)new DynamicProxy().crateProxyInstance(new Mitsubishi())).drive(80);//drive 三菱车
((ICar)new DynamicProxy().crateProxyInstance(new Bwm())).drive(80);//drive 宝马车

3.3 cglib 代理

除了java自身的代理类,还有第三方代理类,比如(cglib),通过实现方法拦截器(MethodInterceptor),在拦截方法中(intercept)调用处理程序的方法。

import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CarInterceptor implements MethodInterceptor{
Object carTarget; //车辆检查
private boolean carCheck() {
if(this.carTarget instanceof Mitsubishi){
System.out.println("Mitsubishi 检查冷却液完成。");
return true;
}else if(this.carTarget instanceof Bwm){
System.out.println("Bwm 检查机油完成。");
return true;
}else{
System.out.println("该车不需要检查。");
return true;
}
}
//拦截方法
@Override
public Object intercept(Object carTarget, Method method, Object[] args, MethodProxy proxy) throws Throwable {
this.carTarget=carTarget;
if(carCheck()){//汽车检查通过后drive
Object obj=proxy.invokeSuper(carTarget, args);
return obj;
}
return null;
}
}

最后调用时,首先实例化(Enhancer)对象启用方法拦截器,设置方法拦截类和Superclass;

Enhancer en=new Enhancer();
en.setCallback(new CarInterceptor());//设置拦截类
//drive 三菱车
en.setSuperclass(new Mitsubishi().getClass());//设置superClass
((ICar) en.create()).drive(80);
//drive 宝马车
en.setSuperclass(new Bwm().getClass());
((ICar) en.create()).drive(100);

4 总结

静态代理更像是开发层面的实现,每次修改接口类或实现类都可能需要修改代理类,随着程序扩展,代码量和维护量增加;Java 提供的(java.lang.reflect.InvocationHandler)代理实例接口和第三方代理类(cglib)大大弥补了静态类的不足,也应用在许多开源框架上,比如Spring。

参考文献

Java程序中的代理作用和应用场景及实现的更多相关文章

  1. java程序中获取kerberos登陆hadoop

    本文由作者周梁伟授权网易云社区发布. 一般我们在使用kbs登陆hadoop服务时都直接在shell中调用kinit命令来获取凭证,这种方式简单直接,只要获取一次凭证之后都可以在该会话过程中重复访问.但 ...

  2. Linux上从Java程序中调用C函数

    原则上来说,"100%纯Java"的解决方法是最好的,但有些情况下必须使用本地方法.特别是在以下三种情况: 需要访问Java平台无法访问的系统特性和设备: 通过基准测试,发现Jav ...

  3. 在网页程序或Java程序中调用接口实现短信猫收发短信的解决方案

    方案特点: 在网页程序或Java程序中调用接口实现短信猫收发短信的解决方案,简化软件开发流程,减少各应用系统相同模块的重复开发工作,提高系统稳定性和可靠性. 基于HTTP协议的开发接口 使用特点在网页 ...

  4. 如何在java程序中调用linux命令或者shell脚本

    转自:http://blog.sina.com.cn/s/blog_6433391301019bpn.html 在java程序中如何调用linux的命令?如何调用shell脚本呢? 这里不得不提到ja ...

  5. Java程序中调用Python脚本的方法

    在程序开发中,有时候需要Java程序中调用相关Python脚本,以下内容记录了先关步骤和可能出现问题的解决办法. 1.在Eclipse中新建Maven工程: 2.pom.xml文件中添加如下依赖包之后 ...

  6. 在java程序中访问windows有用户名和密码保护的共享目录

    在java程序中访问windows有用户名和密码保护的共享目录 Posted on 2015-11-20 14:03 云自无心水自闲 阅读(3744) 评论(0)  编辑  收藏 --> Jav ...

  7. java程序中默认浮点形值常量是什么类型的?如何区分不同类型的浮点型整数值常量?

    java程序中默认浮点形值常量是什么类型的 默认的所有的浮点型数值都是double型

  8. java程序中默认整形值常量是什么类型的?如何区分不同类型的整型数值常量?

    java程序中默认整形值常量是什么类型的?如何区分不同类型的整型数值常量? 整数值默认就是int类型,只有在数值常量后面加“L”或“l”才表明该常量是long型

  9. Derby安装,创建数据库,在Java程序中使用Derby

    1,下载并安装Derby: 下载地址:http://db.apache.org/derby /derby_downloads.html,下载最新版本. 我用的是10.5.3.0. 解压缩到任意文件夹, ...

随机推荐

  1. reStructuredText(.rst) && read the docs

    Read the Docs   &&  reStructuredText (.rst)  && markdown 1. github master 分支,创建 docs ...

  2. Microsoft Lifecycle Policy

    Microsoft Lifecycle Policy The Microsoft Lifecycle Policy gives you consistent and predictable guide ...

  3. how to disabled alert function in javascript

    how to disabled alert function in javascript alert 阻塞主线程 default alert; // ƒ alert() { [native code] ...

  4. how to measure function performance in javascript

    how to measure function performance in javascript Performance API Performance Timeline API Navigatio ...

  5. mobile chart & f2

    mobile chart & f2 https://www.yuque.com/antv/f2/getting-started https://antv.alipay.com/zh-cn/f2 ...

  6. js & disabled right click & disabled right menu

    js & disabled right click (() => { const log = console.log; log(`disabled copy`); document.bo ...

  7. Puppeteer: 鼠标移动

    文档 mouse.click 是 mouse.move,mouse.down 和 mouse.up 的快捷方式 main.js const pptr = require('puppeteer'); c ...

  8. K8S部署Redis Cluster集群(三主三从模式) - 部署笔记

    一.Redis 介绍 Redis代表REmote DIctionary Server是一种开源的内存中数据存储,通常用作数据库,缓存或消息代理.它可以存储和操作高级数据类型,例如列表,地图,集合和排序 ...

  9. Vue学习笔记-基于CDN引入方式简单前后端分离项目学习(Vue+Element+Axios)

    一  使用环境 开发系统: windows 后端IDE: PyCharm 前端IDE: VSCode 数据库: msyql,navicat 编程语言: python3.7  (Windows x86- ...

  10. 在js中如何将字符串类型的日期("2020-11-30T02:21:42.000+0000")进行格式化

    1.引入方法 import { formatDateNew } from '@/utils' 2.在方法中使用,注意要先将字符串进行new Date(),否则报错date.getFullYear is ...