1. 代理模式
代理(Proxy)是一种设计模式,提供了间接对目标对象进行访问的方式,即通过代理对象访问目标对象,可以在目标对象实现的功能上,增加额外的功能,即扩展目标对象的功能。
举个例子来说明就是房东和中介的关系,房东出租房子的时候,房东就属于目标对象,他只要负责提供房子这个核心,而其他有关出租琐碎的事是都由中介(代理)去完成。
2.静态代理
使用静态代理,代理对象和被代理对象都要实现相同的接口或者继承相同的父类,因此需定义一个接口或者抽象类。在代理类中需持有被代理对象的引用在代理类的方法中调用该对象的方法。
接口:
public interface TestInterface {
void say();
}
被代理类:
public class Test implements TestInterface{
@Override
public void say() {
System.out.println("Hello world!");
}
}
代理类:
public class TestProxy implements TestInterface{
private TestInterface testInterface = new Test();
@Override
public void say() {
System.out.println("Before invoke Test" );
testInterface.say();
System.out.println("After invoke Test");
}
}
代理类的调用:
代理类在执行具体方法时通过所持用的被代理类完成调用。
public static void main(String[] args) {
TestProxy testProxy = new TestProxy();
testProxy.say();
}
输出:
Before invoke Test
Hello world!
After invoke Test
静态代理能在不修改目标对象的功能下对其进行扩展但需要代理的类数量很多,就需要编写大量的代理类,而且接口的方法一旦增加,代理对象和目标对象都需要维护。
3.动态代理
利用反射机制,程序在运行时JVM才为被代理对象创建代理对象。在接口和被代理类不变的情况下,构建一个handler类实现InvocationHandler接口。
public class ProxyHandler implements InvocationHandler{
private Object object;//被代理对象
public ProxyHandler(Object object){
//构造方法
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before invoke " + method.getName());
method.invoke(object, args);
System.out.println("After invoke " + method.getName());
return null;
}
}
执行动态代理:
public static void main(String[] args) {
System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
TestInterface test= new Test();
InvocationHandler handler = new ProxyHandler(test);
TestInterface proxyTest = (TestInterface) Proxy.newProxyInstance(test.getClass().getClassLoader(), test.getClass().getInterfaces(), handler);
proxyTest.say();
}
输出:
Before invoke say
Hello world!
After invoke say
通过Proxy类的静态方法newProxyInstance返回一个接口的代理实例。针对不同的代理类,传入相应的代理程序控制器InvocationHandler。
设置新的被代理类Tests
public interface TestsInterface {
void sayTests();
}
public class Tests implements TestsInterface {
@Override
public void sayTests() {
System.out.println("Test success");
}
}
执行过程
public static void main(String[] args) {
System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
TestInterface test = new Test();
TestsInterface tests = new Tests();
InvocationHandler handler = new ProxyHandler(test);
InvocationHandler handler1 = new ProxyHandler(tests);
TestInterface proxyTest = (TestInterface) Proxy.newProxyInstance(test.getClass().getClassLoader(),tset.getClass().getInterfaces(), handler);
TestsInterface proxyTests = (TestsInterface) Proxy.newProxyInstance(tests.getClass().getClassLoader(), tests.getClass().getInterfaces(), handler1);
proxyTest.say();
proxyTests.sayTests();
}
输出:
Before invoke say
Hello world!
After invoke say
Before invoke sayTests
Test success
After invoke Tests
动态代理的具体步骤:
1.通过实现InvocationHandler 接口创建自定义调用处理器;
通过实现 InvocationHandler 接口创建自己的调用处理器;
2.通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
3.通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
4.通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。