代理(Proxy)是一种设计模式,通过为一个对象创建目标代理对象,通过这个代理对象去扩展一些被代理对象没有的方法,这样就可以在不修改对象的前提下,增加对象的功能。
代理分为静态代理和动态代理。
静态代理是为每个需要代理的对象都创建一个代理对象。代理对象需要和被代理的对象实现相同的接口才能去代理,否则无法进行被代理对象的代理。
以下使用以下例子进行加深了解:小明是一个歌手会唱歌,在小明举行演唱会的时,需要联系好场地、谈好场地费,在演唱会结束后,需要小明去打扫卫生。这样的话,小明就需要从一个歌手只需要完成唱歌功能的人变成了一个全能型人才了。虽然变成一个全能型人才很棒,但这需要时间,就怕等小明变成全能型人才的时候,好长时间也就过去了。所以需要一个代理公司去帮助他去完成这些事情,这样小明就可以专心的去唱歌了,不用因为一些其他不相关的事情浪费时间。这个代理公司就是一个代理对象,小明就是一个被代理的对象。小明和这个代理公司都需要实现的接口就是唱歌接口,他们都必须告诉别人他会唱歌才会有人找他。
代码如下:
需要实现的接口:
/**
* 唱歌接口,只有实现这个接口,才能让别人知道你会唱歌
* @author zzw
*
*/
public interface Sing {
public void sing();
}
目标对象
/**
* 被代理的目标对象
* 在这个对象中,歌手只需要去唱歌就行,不用去管其他的事情
* @author zzw
*
*/
public class Singer implements Sing {
@Override
public void sing() {
System.out.println("你我皆凡人 生在人世间 终日奔波苦 一刻不得闲");
}
}
代理对象
/**
* 唱片公司
* 唱片公司也需要实现唱歌这个接口,
* 毕竟需要告诉别人,他们这个公司能唱歌,这样才能让别人去找他
* 唱片公司要有歌手
* 唱片公司可以在歌唱开始前去和别人谈场地
* 在歌唱结束后,唱片公司需要把卫生处理好
* @author zzw
*
*/
public class RecordCompany implements Sing {
//歌唱公司拥有的歌手
private Singer singer;
public RecordCompany(Singer singer) {
this.singer = singer;
}
@Override
public void sing() {
before();
singer.sing();
after();
}
private void before() {
System.out.println("去租场地");
}
private void after() {
System.out.println("清理场地卫生");
}
}
测试类
/**
* 测试类
* @author zzw
*
*/
public class MainClass {
public static void main(String[] args) {
//首先歌手要存在
Singer singer = new Singer();
//唱片公司存在,并要有歌手加入唱片公司
RecordCompany company = new RecordCompany(singer);
//开演唱会,去请一个会唱歌的人唱歌,不管请的是个人还是唱片公司,需要会唱歌
concert(company);
}
/**
* 开演唱会,只需要找到会唱歌的人就可以了
* @param sing 会唱歌的人
*/
public static void concert(Sing sing) {
sing.sing();
}
}
在静态代理模式中,一个代理类只能为一个目标实现代理对象,因为它们需要实现相同的接口,为这个接口进行服务。就比如上面的例子,唱片公司就只能为歌手进行代理,因为唱片公司只实现了唱歌这个接口。如果唱片公司想要举行跳舞比赛,无能为力,只能在开一个用来跳舞的公司。这样的话,就需要创建很多的代理类。
动态代理,就来解决了这个问题。动态代理不需要和目标对象实现相同的接口。在动态代理中,只要能为目标对象做的事情是一样的,就可以为多种目标对象进行代理了。
代码如下:
接口
/**
* 唱歌接口,只有实现这个接口,才能让别人知道你会唱歌
* @author zzw
*
*/
public interface Sing {
public void sing();
}
/**
* 跳舞接口
*/
public interface Dance {
/**
* 跳舞方法
*/
public void dance();
}
目标对象
/**
* 被代理的目标对象
* 在这个对象中,歌手只需要去唱歌就行,不用去管其他的事情
*/
public class Singer implements Sing{
public void sing() {
System.out.println("你我皆凡人 生在人世间 终日奔波苦 一刻不得闲");
}
}
/**
* 被代理的目标对象
* 在这个对象中,舞者只需要去跳舞就行,不用去管其他的事情
*/
public class Dancer implements Dance {
@Override
public void dance() {
System.out.println("跳了天鹅舞");
}
}
代理对象
public class RecordCompany implements InvocationHandler {
// 目标对象
private Object targetObject;
// 通过proxy获取目标对象
public Object newInstance(Object targetObject) {
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),this);
}
// 执行所要做的事情
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object invoke = method.invoke(targetObject, args);
after();
return invoke;
}
//帮目标对象执行的其他操作
private void before() {
System.out.println("去租场地");
}
private void after() {
System.out.println("清理场地卫生");
}
}
在动态代理中,只需要实现java自带的java.lang.reflect.InvocationHandler接口,通过java.lang.reflect.Proxy对象获取想要的对象就可以了,获取的对象在执行自己的操作时,代理类会将一些目标对象需要完成的一些其他操作完成,比如不需要歌手、舞者去自己联系场地、打扫卫生了。
但在动态代理中,目标对象需要实现某个接口,才能够被代理。这个问题在cglib中被解决了,这个解决方法等啥时候想起来看了,再去了解吧,不想往下看了…