代理模式就是为某个对象提供一个代理,以控制对这个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。通过代理类这层,能有效控制对委托类对象的直接访问,也能很好的隐藏和保护委托类对象。
代理类和目标类是一模一样,不允许更改。代理只是控制目标,可以控制让你访问还是不让你访问。而委托类(业务类)只需要关注业务逻辑本身,保证了委托类(业务类)的重用性。
我们根据代理类的生成时间不同,可以将代理分为静态代理和动态代理。
(1)静态代理
所谓的静态代理就是在运行前就已经知道了代理类和委托类的关系。它由程序员创建或工具生成代理类的源码,再编译代理类。下面展示一下静态代理实现代码:
代理接口:
package static_proxy_package;
/**
* 代理接口,送礼物
* @author lsh
*
*/
public interface Subject {
/**
* 某个人送礼物
* @param gift
*/
public void giveGift(String name);
}
委托类:
package static_proxy_package;
/**
* 委托类,真正要送礼物的人,实现了接口
* @author lsh
*
*/
public class RealSubject implements Subject {
@Override
public void giveGift(String name) {
System.out.println(name + "送给了您一份礼物");
}
}
代理类:
package static_proxy_package;
/**
* 代理类,帮助委托人送礼物的人,也实现了代理接口
* @author lsh
*
*/
public class ProxySubject implements Subject {
//代理类持有一个委托类的对象引用
private Subject delegate;
public ProxySubject(Subject delegate){
this.delegate =delegate;
}
@Override
public void giveGift(String name) {
System.out.println("送礼物之前");
delegate.giveGift(name);
System.out.println("送礼物之后");
}
}
客户端:
package static_proxy_package;
import java.lang.reflect.Proxy;
/**
* 客户类
* @author lsh
*
*/
public class Client {
public static void main(String[] args ){
Subject realSubject = new RealSubject();
Subject proxy =new ProxySubject(realSubject);
proxy.giveGift("huazi");
}
}
利用这种静态代理,代理对象的一个接口只服务于一种类型的对象,如果要代理的类型很多,势必要为每一类型都进行代理,静态代理在程序规模稍大时就无法胜任了。另外,可以想一想如果接口要增加一个方法处理所有实现类需要实现这个方法外,所有代理类也需要实现此方法,增加代码的复杂度。
这时我们就可以考虑使用动态代理。Proxy 类是它的父类,这个规则适用于所有由 Proxy 创建的动态代理类。而且该类还实现了其所代理的一组接口,这就是为什么它能够被安全地类型转换到其所代理的某接口的根本原因,这样可以节省不必要的代码重复生成,提高了代理类的创建效率。图示如下:
(2)动态代理:
所谓动态代理就是代理类和委托类的关系是在程序运行时确定的。动态代理类的源码是在运行期间,由JVM根据反射机制动态生成的,不存在代理类的字节码文件。 下面展示一下动态代理代码实现:
代理接口:
package static_proxy_package;
/**
* 代理接口,送礼物
* @author lsh
*
*/
public interface Subject {
/**
* 某个人送礼物
* @param gift
*/
public void giveGift(String name);
}
委托类:
package static_proxy_package;
/**
* 委托类,真正要送礼物的人,实现了接口
* @author lsh
*
*/
public class RealSubject implements Subject {
@Override
public void giveGift(String name) {
System.out.println(name + "送给了您一份礼物");
}
}
代理类:
package static_proxy_package;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 采用动态代理调用程序处理类
* @author lsh
*
*/
public class proxyHandler implements InvocationHandler {
//代理类持有一个委托类的对象引用
private Object delegate;
public proxyHandler(Object delegate){
this.delegate=delegate;
}
public Subject getInstance(){
return (Subject)Proxy.newProxyInstance(delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object sub= null;
System.out.println("送礼物之前");
sub=method.invoke(delegate, args);
System.out.println("送礼物之后");
return sub;
}
}
客户端:
package static_proxy_package;
import java.lang.reflect.Proxy;
/**
* 客户类
* @author lsh
*
*/
public class Client {
public static void main(String[] args ){
//定义一个委托对象
Subject delegate = new RealSubject();
//定义一个动态代理类
proxyHandler handler = new proxyHandler(delegate);
Subject proxy=handler.getInstance();
proxy.giveGift("huazi");
}
}
这就是静态代理和动态代理的简单介绍。下面做一下静态代理和动态代理的简单总结:
对java中动态代理的实现还有诸多疑惑,接下来我会对动态代理的实现原理整理和理解一下。