Java基本六:代理
来源:互联网 发布:程序员大神是什么样子 编辑:程序博客网 时间:2024/06/06 00:05
代理其实理解起来很简单,就是代理者代理被代理者去做完成一些事情,并且增加一些自己附加的行为。比如将军下达命令到士兵,那么将军肯定不是亲自去士兵面前然后命令,而是找人传达命令到士兵面前。士兵执行命令。暂且将这个传达命令的人员称为传达员bellman。这就是代理的一个例子。传达员代理将军执行命令。
在Java中有静态代理和动态代理。动态代理又有jdk、cglib、Javassist、asm等。动态代理只说jdk代理。
静态代理就是我们写好的代理类进行代理。
静态代理
士兵类:
public class Soldier {
protected String name;
protected int age;
protected String gunName;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGunName() {
return gunName;
}
public void setGunName(String gunName) {
this.gunName = gunName;
}
public void shoot(){
System.out.println(age+"岁的"+name+"拿着"+gunName+"射击");
}
public void run(){
System.out.println(age+"岁的"+name+"拿着"+gunName+"跑步");
}
}
海军士兵
public class SeaSoldier extends Soldier{
public void sail(){
System.out.println(age+"岁的"+name+"开船");
}
@Override
public void shoot() {
// TODO Auto-generated method stub
System.out.println(age+"岁的"+name+"在水下拿着"+gunName+"射击");
}
}
将军类:
public class General extends Soldier implements Commander{
private int level;
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
@Override
public void executeCommand(Command command) {
// TODO Auto-generated method stub
System.out.println(age+"岁的"+name+"命令:");
command.commandExcute();
}
}
命令者接口:
public interface Commander {
void executeCommand(Command command);
}
命令接口:
public interface Command {
void commandExcute();
}
跑路命令类:
public class Run implements Command{
private Soldier soldier;
public Run(Soldier soldier) {
super();
this.soldier = soldier;
}
public Soldier getSoldier() {
return soldier;
}
public void setSoldier(Soldier soldier) {
this.soldier = soldier;
}
@Override
public void commandExcute() {
// TODO Auto-generated method stub
System.out.println(soldier.name+"执行命令");
soldier.run();
}
}
那么需要声明一个传达员类来代理将军执行命令,也就是代理命令者执行命令。
那么可以这样写:
public class BellMan implements Commander{
private Commander commander;
public BellMan(Commander commander) {
// TODO Auto-generated constructor stub
this.commander=commander;
}
public BellMan() {
// TODO Auto-generated constructor stub
}
public void setCommander(Commander commander) {
this.commander = commander;
}
@Override
public void executeCommand(Command command) {
// TODO Auto-generated method stub
System.out.println("命令之开始时间:"+System.currentTimeMillis());
commander.executeCommand(command);
System.out.println("命令之结束时间:"+System.currentTimeMillis());
}
}
传达员代理执行命令,并且还需要监视命令执行,上报完成情况。这里完成的情况,就打印处理。不仅仅是将军的命令,传达员可以代理执行,其它上级的命令,传达员都可以代理执行,并且监视上报命令完成情况。这样代理的好处就是命令者只关注命令本身,其它的统一的操作,都可以交给代理者进行完成。不必每一个命令者都需要亲自去完成监视和上报命令的执行情况。
这样的设计也是方便扩展,修改。如果交给命令者去完成监视的行动,那么监视的方式变了,需要去修改每一个命令者的方法,这样不易于修改。代理者模式,只需要去修改代理者的方法就可以 完成对所有命令者的那么其余的行为的修改了。
测试执行:
Soldier soldier=new Soldier();
soldier.setName("小明");soldier.setAge(18);soldier.setGunName("手枪");
Command command=new Run(soldier);
General general=new General();
general.setName("威灵顿");general.setAge(55);general.setGunName("手枪");general.setLevel(2);
BellMan bellMan=new BellMan(general);
bellMan.executeCommand(command);
这些代码中也结合了命令者模式,
士兵可以有好多种士兵,命令也是可以是好多种命令,命令者仍然是可以是将军或者其它高级的将领。那么传达员只关注命令者接口,来代理执行命令。
动态代理
Java的动态代理,是运行时修改对象的内容,对对象的方法等进行重写,改变。这仅仅是个人理解。
代理生成对象:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProCommander implements InvocationHandler{
private Commander commander;
public void setCommander(Commander commander) {
this.commander = commander;
}
public ProCommander(Commander commander) {
// TODO Auto-generated constructor stub
this.commander=commander;
}
public Commander getProxyCommander() {
return (Commander) Proxy.newProxyInstance(commander.getClass().getClassLoader(), commander.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
System.out.println("命令之开始时间:"+System.currentTimeMillis());
Object invoke = method.invoke(commander, args);
System.out.println("命令之结束时间:"+System.currentTimeMillis());
return invoke;
}
}
可以看出实现了InvocationHandler接口,这个接口就是来处理代理的其它操作的。实现invoke方法。最后获取代理对象,由Proxy对象生成一个新的代理实例,传入对象的类加载器和对象的接口数组,又传入这个代理类处理操作的接口。
测试执行:
Soldier soldier=new Soldier();
soldier.setName("小明");soldier.setAge(18);soldier.setGunName("手枪");
Command command=new Run(soldier);
General general=new General();
general.setName("威灵顿");general.setAge(55);general.setGunName("手枪");general.setLevel(2);
ProCommander proCommander=new ProCommander(general);
Commander commander = proCommander.getProxyCommander();
commander.executeCommand(command);
执行的结果和静态代理的执行结果是一样的。
代理生成对象,又可以被称为拦截器。拦截一个方法,在方法执行前和执行后都可以进行一系列的操作。
这样的话,拦截器可以拦截一切对象的的方法,那么拦截器可以这样改:
拦截方法接口:
public interface InterceptorMothod {
void before();
void after();
}
代理类:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyObject implements InvocationHandler{
private Object object;
private InterceptorMothod interceptorMothod;
public void setInterceptorMothod(InterceptorMothod interceptorMothod) {
this.interceptorMothod = interceptorMothod;
}
public void setCommander(Object object) {
this.object = object;
}
public ProxyObject(Object object) {
// TODO Auto-generated constructor stub
this.object=object;
}
public Object getProxyCommander() {
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
interceptorMothod.before();
Object invoke = method.invoke(object, args);
interceptorMothod.after();
return invoke;
}
}
这样就对所有的类的方法进行了拦截。进行了其它的额外的方法执行。如果想对特殊的方法进行拦截,那么也简单,只需要判断对象的类名和方法的名字就可以拦截。
代理有什么用呢?用处多了,日志、跟踪、验证等。在spring 的beans 中的aop的配置就是这个代理的配置。这里只是简单的写了原理,类的拦截,包的拦截,方法的拦截,这里没做过多的说明。
- Java基本六:代理
- Java代理模式 ------基本消化
- JAVA设计模式之六代理模式
- 走进Java(六)静态代理和动态代理
- Java(六) 基本API和字符串
- 【Java】基本类型之long(六)
- Java动态代理的基本用法
- java 设计模式学习笔记六 proxy代理模式
- 浅析JAVA设计模式之代理模式(六)
- Java设计模式(六) 代理模式 VS. 装饰模式
- Java设计模式(六) 代理模式 vs. 装饰模式
- 高新技术<六>---> 代理
- 从java 反射看延迟加载(代理模式)(六)——动态代理与静态代理
- Java基本的六种排序(方法部分)
- Java单链表基本操作(六)--删除重复节点;
- java加载properties文件的六种基本方式
- java加载properties文件的六种基本方式
- 设计模式(六)---代理模式
- 分数加减法
- Android双屏驱动Service架构实现
- 细说java对象的浅复制和深复制
- 如何写toolbar
- 键盘Key Code对照表和 ASCII 字符集
- Java基本六:代理
- caffe学习资料
- 第八周—C语言 穷举法(换分币问题)
- JEECG弹出表单调用列表刷新
- Java 访问修饰符
- 通信协议——Http、TCP、UDP(个人理解)
- leetcode412: Fizz Buzz
- Scala-maven-plugin and Multiple Versions of Scala Libraries Detected
- 第八周 鸡兔共笼