动态代理
动态代理:运行时动态的创建代理类(对象),并将方法调用转发到指定类(对象)
动态代理调用的机制图
Proxy
和InvocationHandler
组合充当代理的角色.RealSubject
是一个实际对象,它实现接口Subject- 在使用时,我们不希望直接访问 RealSubject 的对象,比如:我们对这个对象的访问是有控制的
- 我们使用动态代理,在程序中通过动态代理创建 RealSubject,并完成调用.
- 动态代理可以根据需要,创建多种组合
- Proxy 也会实现 Subject 接口的方法,因此,使用 Proxy+Invocation 可以完成对 RealSubject 的动态调用。
- 但是通过 Proxy 调用 RealSubject 方法是否成功,是由 InvocationHandler 来控制的。(这里其实就是保护代理)
- 理解:创建一个代理对象替代被调用的真实对象,使用反射实现控制
JDK动态代理实现示例代码
创建被代理对象的接口类Subject
public interface Subject {
void request();
}
创建Subject接口的实现类:简单打印一句输出
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("request invoke");
}
}
创建一个InvocationHandler
的实现类
public class ConcreteInvocationHandler implements InvocationHandler {
private Subject subject;
public ConcreteInvocationHandler(Subject subject) {
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return method.invoke(subject, args);
}
}
注意:
InvocationHandler
可以控制安全访问, 作为保护代理
这部分演示语言为Scala, 见谅, 看懂意思就行.
override def invoke(proxy: scala.Any, method: Method, args: Array[AnyRef]): AnyRef = {
//如果是get方法就直接调用
if (method.getName().startsWith("get")) {
return method.invoke(person)
//自己不能调用setHotOrNotRating,给自己评分
} else if (method.getName().equals("setScore")) {
//返回一个异常,同时invoke throws掉了
return new IllegalAccessException()
}
null
}
客户端测试类
public class JDKDynamicProxyTest {
public static void main(String[] args) {
Subject subject = new RealSubject();
InvocationHandler handler = new ConcreteInvocationHandler(subject);
Subject proxy = (Subject)Proxy.newProxyInstance(RealSubject.class.getClassLoader(),
RealSubject.class.getInterfaces(), handler);
proxy.request();
}
}