代理模式:使用代理对象来执行目标对象的方法并在代理对象中增强目标对象方法的一种设计模式。
代理模式的元素是:共同接口、代理对象、真实对象。
代理模式的行为:由代理对象执行目标对象的方法、由代理对象扩展目标对象的方法。
代理模式的宏观特性:对客户端只暴露出接口,不暴露它以下的架构。
2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
Object invoke(Object proxy,Method method,Object[] args) throws Throwable
在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
proxy - 在其上调用方法的代理实例
method - 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
loader - 定义代理类的类加载器
interfaces - 代理类要实现的接口列表
h - 指派方法调用的调用处理程序
上面的代码实含义也就是,输入真实类、共同的接口,返回一个代理对象。
代理模式的元素是:共同接口、代理对象、真实对象。
代理模式的行为:由代理对象执行目标对象的方法、由代理对象扩展目标对象的方法。
代理模式的宏观特性:对客户端只暴露出接口,不暴露它以下的架构。
静态代理
静态代理需要自己来创建代理对象,需要自己写出来共同的接口
public interface Action {
public void dosomething();
}
接口的实现类,也就是真实对象
public class Actionimpl implements Action {
@Override
public void dosomething() {
System.out.println("dosomething.");
}
}
代理对象
public class Proxy implements Action {
private Actionimpl actionimpl;
public Proxy(Actionimpl actionimpl) {
this.actionimpl=actionimpl;
}
@Override
public void dosomething() {
System.out.println("增加功能");
actionimpl.dosomething();
}
}
运行代码
public static void main(String[] args) {
Proxy proxy = new Proxy(new Actionimpl());
proxy.dosomething();
}
静态代理类优缺点
优点:
业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。缺点:
1)代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
动态代理
为了解决静态代理的弊端,而且代理对象由底层创建,不需要自己写出来动态代理用到了一个接口和一个类
InvocationHandler接口
代理实例的调用处理程序 实现的接口。Object invoke(Object proxy,Method method,Object[] args) throws Throwable
在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
proxy - 在其上调用方法的代理实例
method - 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。
Proxy类
提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
loader - 定义代理类的类加载器
interfaces - 代理类要实现的接口列表
h - 指派方法调用的调用处理程序
上面的代码实含义也就是,输入真实类、共同的接口,返回一个代理对象。
共同的接口
public interface Action {
public void dosomething();
}
接口的实现类,也就是真实对象
public class Actionimpl implements Action {
@Override
public void dosomething() {
System.out.println("dosomething.");
}
}
动态代理,需要将要扩展的功能写在一个InvocationHandler 实现类里
public class MyinvocationHandler implements InvocationHandler {
private Object actionimpl;
public MyinvocationHandler(Object actionimpl) {
this.actionimpl = actionimpl;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("增加功能");
return method.invoke(actionimpl, args);
}
}
然后运行程序
public static void main(String[] args) {
Actionimpl ac = new Actionimpl();
Action a =(Action)Proxy.newProxyInstance(ac.getClass().getClassLoader(),
ac.getClass().getInterfaces(),
new MyinvocationHandler(ac));
a.dosomething(); //可以调用其它方法,会动态创建方法的代理
}