import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* JDK动态代理
*/
public class JdkProxyTest {
//定义一个接口
public interface Hello {
public void sayHello();
}
//接口实现
public static class HelloImpl implements Hello {
public void sayHello() {
System.out.println("Hello world!!");
}
}
//第一种采用构造方法模式
public static class JdkInvocationHandler1 implements InvocationHandler {
//真实对象
private Object target;
public JdkInvocationHandler1(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("------进入代理之前-------------");
Object obj = method.invoke(target, args);
System.out.println("------进入代理之后-------------");
return obj;
}
}
//第二种采用普通方法模式
public static class JdkInvocationHandler2 implements InvocationHandler {
//真实对象
private Object target;
/**
* 第一步:建立代理对象与真实对象的代理关系,并返回代理对象
* @param target 真实对象
* @return 代理对象
*/
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);/***
通过 Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this);建立了代理对象与真实对象的关系,第一个参数是类加载器,这里我们传入的就是HelloImpl的类加载器,第二个参数是动态代理对象下挂那些接口,这里就是Hello接口,这个参数的类型是Class<?>[],第三个参数是实现代理方法逻辑的实现类,也就是invoke方法的实现类,所以这里就是this。
通过invoke(Object proxy, Method method, Object[] args)实现了代理逻辑,第一个参数是代理对象,也就是bind方法返回的对象,第二个参数是当前调度的方法,args是调度方法的参数。这里其实是用到了JAVA反射方法的机制,实现代理对象到真实对象方法的调用。
*/
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("------进入代理之前-------------");
Object obj = method.invoke(target, args);
System.out.println("------进入代理之后-------------");
return obj;
}
}
public static void main(String[] args) {
/**
* 1.通过实现InvocationHandler接口来自定义自己的InvocationHandler;
2.通过Proxy.getProxyClass获得动态代理类
3.通过反射机制获得代理类的构造方法,方法签名为getConstructor(InvocationHandler.class)
4.通过构造函数获得代理对象并将自定义的InvocationHandler实例对象传为参数传入
5.通过代理对象调用目标方法
*/
//生成动态代理类
Class<?> clazz = Proxy.getProxyClass(Hello.class.getClassLoader(), Hello.class);
try {
//获得代理类的构造函数,并传入参数类型InvocationHandler.class
Constructor<?> constructor = clazz.getConstructor(InvocationHandler.class);
//通过构造函数来创建动态代理对象,将自定义的InvocationHandler实例传入
Hello hello = (Hello) constructor.newInstance(new JdkInvocationHandler1(new HelloImpl()));
//通过代理对象调用目标方法
hello.sayHello();
} catch (Exception e) {
e.printStackTrace();
}
/**
* Proxy类中还有个将2~4步骤封装好的简便方法来创建动态代理对象,
* 其方法签名为:newProxyInstance(ClassLoader loader,
* Class<?>[] instance, InvocationHandler h)
*/
Hello helloImpl1=(Hello)Proxy.newProxyInstance(HelloImpl.class.getClassLoader(), HelloImpl.class.getInterfaces(), new JdkInvocationHandler1(new HelloImpl()));
//通过代理对象调用目标方法
helloImpl1.sayHello();
/**---------------------------------------------------------------------*/
JdkInvocationHandler2 jdkInvocationHandler2=new JdkInvocationHandler2();
Hello helloImpl=(Hello) jdkInvocationHandler2.bind(new HelloImpl());
//通过代理对象调用目标方法
helloImpl.sayHello();
}
}输出------进入代理之前-------------
Hello world!!
------进入代理之后-------------
------进入代理之前-------------
Hello world!!
------进入代理之后-------------
------进入代理之前-------------
Hello world!!
------进入代理之后-------------