JDK动态代理

静态代理都是针对要代理的对象的方法写死成Java代码,然后调用静态代理对象的对应方法即可。

动态代理就是一个代理对象,可以对传入的任何对象动态的生产代理对象,然后就可以通过代理对象调用目标方法。

下面是JDK的动态代理示例:

// JDK动态代理的对象类必须实现接口

// 接口
public interface Subject {

	void request();
	
	void response();
}

// 目标对象类,实现接口
public class SubjectImpl implements Subject {
	
	public void request() {
		System.out.println("执行 request 方法了。。。");
	}

	public void response() {
		System.out.println("执行 response 方法了。。。");
	}
}

JDK动态代理对象必须要实现 InvocationHandler 接口(JDK反射包里的接口)。

public class SubjectJDKProxy implements InvocationHandler {
	
	private Subject subject;

	public void setSubject(Subject subject) {
		this.subject = subject; // 设置代理的目标对象
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// 执行目标方法前的非业务功能
		System.out.println("before 前置通知");
		Object result;
		try {
			// 执行目标方法
			result = method.invoke(subject, args);
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		} finally {
			// 执行目标方法后的非业务功能
			System.out.println("after 后置通知");
		}
		return result;
	}
}

获取代理对象:

public class JDKProxyMain {
	public static void main(String{} args) {
		SubjectJDKProxy handler = new SubjectJDKProxy(new SubjectImpl());
		// 获取代理对象
		Subject subject = (Subject)Proxy.newProxyInstance(JDKProxyMain.class.getClassLoader, new Class[]{Subject.class}, handler);

		subject.request();
		subject.response();
	}
}

输出结果:

before 前置通知
执行 request 方法了。。。
after 后置通知
before 前置通知
执行 response 方法了。。。
after 后置通知

可以参考 代理模式详解及源码分析 知道,代理对象的源码:

public final class $Proxy0 extends Proxy implements Subject { // 继承父类Proxy,实现自定义接口Subject 

    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m4;
    private static Method m0;

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            m4 = Class.forName("mike.test.Starter").getMethod("request");
            m3 = Class.forName("mike.test.Starter").getMethod("response");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
    
    public $Proxy0(InvocationHandler var1) throws  { // 构造方法接收代理人,并调用Proxy父类构造方法
        super(var1);
    }
	
    public final void request() throws  { // 实际上其实是调用了代理人SubjectJDKProxy的invoke方法(h 其实就是我们所创建的 subjectJDKProxy 对象,m4 就是目标类实现接口中的方法)
        try {
            super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    
    public final void response() throws  { // 实际上其实是调用了代理人SubjectJDKProxy的invoke方法
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
	
	// 以下就是Object类通用方法的覆盖,不多赘述
    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
}

所以,这段代码的作用就是生成最终的代理对象,方式就是获取到 Subject.class 接口中的所有方法,生成一个新的字节码类,在字节码类中注入 属性 handler,通过 handler 的 invok 方法调用目标对象的方法。

Proxy.newProxyInstance(JDKProxyMain.class.getClassLoader, new Class[]{Subject.class}, handler)

你可能感兴趣的:(java)