版权声明:欢迎转载,请注明作者和出处 https://blog.csdn.net/baichoufei90/article/details/83305446
Java学习-动态代理
0x01 摘要
我们在看源码的时候,往往能发现很多实用动态代理的例子,本文将对其进行简要介绍。
0x02 概念
在不想直接暴露真实对象,且想再对象的方法前后增加逻辑时可以用代理。
代理类和被代理类实现共同接口,且代理类可以访问被代理类的实际对象,在其方法调用前后增加自定义的逻辑。
代理的好处就是隐藏了真实对象,且可加逻辑处理代码。这一切对客户端来说是无感知的。
0x03 被代理对象和接口
public interface Interface {
void doSomething();
void somethingElse(String arg);
}
class RealObject implements Interface {
@Override
public void doSomething() {
System.out.println("doSomething.");
}
@Override
public void somethingElse(String arg) {
System.out.println("somethingElse " + arg);
}
}
0x04 简陋的代理
代码如下:
class SimpleProxy implements Interface {
private Interface proxy;
public SimpleProxy(Interface proxy) {
this.proxy = proxy;
}
@Override
public void doSomething() {
System.out.println("SimpleProxy doSomething.");
proxy.doSomething();
}
@Override
public void somethingElse(String arg) {
System.out.println("SimpleProxy somethingElse " + arg);
proxy.somethingElse(arg);
}
}
0x05 InvocationHandler实现动态代理
动态代理代码示例如下:
class DynamicProxyHandler implements InvocationHandler {
//要代理的原始对象
private Object proxy;
//传入被代理的对象
public DynamicProxyHandler(Object proxy) {
this.proxy = proxy;
}
/**
* 在代理实例上处理方法调用并返回结果
* @param proxy 被代理对象
* @param method 被代理的方法
* @param args 该方法的参数数组
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("method.getDeclaringClass() = "+ method.getDeclaringClass());
// 这一步的作用是为了防止调用继承自Object的方法如 toString hashCode等
// 也就是说,接口创建出的代理对象不仅有接口的方法,还有从Object类继承的方法
if (method.getDeclaringClass()== Object.class) {
return method.invoke(this, args);
}
System.out.println("*** proxy: " + proxy.getClass() +
". method: " + method + ". args: " + args);
System.out.println("something you need do before invoking");
if(args != null) {
for(Object arg : args)
System.out.println(" " + arg);
}
//调用方法
Object result = method.invoke(this.proxy, args);
System.out.println("something you need do after invoking");
return result;
}
}
0x06 测试代码
客户端调用测试代码如下:
public static void main(String[] args) {
Parent real = new RealObject();
real.doSomething();
real.somethingElse("bonobo");
System.out.println("--------------------------Insert a Simple proxy and call again");
consumer(new SimpleProxy(real));
System.out.println("--------------------------Insert a dynamic proxy and call again");
System.out.println(real.getClass().getInterfaces().length);
System.out.println(new Class[]{ Interface.class }.length);
/**
* @param loader the class loader to define the proxy class
* @param interfaces the list of interfaces for the proxy class to implement
* @param h the invocation handler to dispatch method invocations to
* @return a proxy instance with the specified invocation handler of a
* proxy class that is defined by the specified class loader
* and that implements the specified interfaces
*/
Interface proxy = (Interface)Proxy.newProxyInstance(
RealObject.class.getClassLoader(),
new Class[]{ Interface.class },
new DynamicProxyHandler(real));
Interface proxy2 = (Interface)Proxy.newProxyInstance(
real.getClass().getClassLoader(),
real.getClass().getInterfaces(),
new DynamicProxyHandler(real));
consumer(proxy2);
}