代理模式是常用的Java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。
代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。按照代理类的创建时期,代理类可分为两种。
静态代理类:
由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。实现类和代理类实现同一个接口,将实现类对象传递给代理类,代理类的实现方法实际是由实现类完成操作的。
动态代理类:
在程序运行时,运用反射机制动态创建而成。
静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类。
静态代理事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道。
动态代理是实现JDK里的InvocationHandler接口的invoke方法,但注意的是代理的是接口,也就是你的业务类必须要实现接口,通过Proxy里的newProxyInstance得到代理对象。
还有一种动态代理CGLIB,代理的是类,不需要业务类继承接口,通过派生的子类来实现代理。通过在运行时,动态修改字节码达到修改类的目的。
静态代理Demo
public interface Iuser {
void eat(String s);
}
public class UserImpl implements Iuser {
@Override
public void eat(String s) {
System.out.println("我要吃"+s);
}
}
public class DynamicProxy implements InvocationHandler {
private Object object;//用于接收具体实现类的实例对象
//使用带参数的构造器来传递具体实现类的对象
public DynamicProxy(Object obj){
this.object = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
System.out.println("前置内容");
method.invoke(object, args);
System.out.println("后置内容");
return null;
}
}
public class ProxyTest {
public static void main(String[] args) {
Iuser user = new UserImpl();
InvocationHandler h = new DynamicProxy(user);
Iuser proxy = (Iuser) Proxy.newProxyInstance(Iuser.class.getClassLoader(), new Class[]{Iuser.class}, h);
proxy.eat("苹果");
}
}
动态代理Demo
public interface Iuser {
void eat(String s);
}
public class UserImpl implements Iuser {
@Override
public void eat(String s) {
System.out.println("我要吃"+s);
}
}
public class DynamicProxy implements InvocationHandler {
private Object object;//用于接收具体实现类的实例对象
//使用带参数的构造器来传递具体实现类的对象
public DynamicProxy(Object obj){
this.object = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
System.out.println("前置内容");
method.invoke(object, args);
System.out.println("后置内容");
return null;
}
}
public class ProxyTest {
public static void main(String[] args) {
Iuser user = new UserImpl();
InvocationHandler h = new DynamicProxy(user);
Iuser proxy = (Iuser) Proxy.newProxyInstance(Iuser.class.getClassLoader(), new Class[]{Iuser.class}, h);
proxy.eat("苹果");
}
}