Java动态代理机制:不需要开发人员手动编写代理类,只需要简单地指定一组接口以及委托类对象,即可动态获取代理类。而代理类会将所有的方法调用分派到委托对象上进行反射执行。动态代理的作用最终是学习AOP(面向切面编程),与装饰者模式相似,但比装饰者模式更加灵活。
动态代理相关的类
java.lang.reflect.Proxy:java动态代理主类,该类提供了一组静态方法来为一组接口动态生成代理类以及对象。
Proxy类方法(静态)
getInvocationHandler(Object proxy) 返回指定代理实例的调用处理程序
getProxyClass(ClassLoader loader,Class[] interfaces) 返回代理类的java.lang.Class对象
isProxyClass(Class c) 判断指定类对象是否是动态代理类
newProxyinstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序
参数:loader 定义代理类的类加载器(把.class文件加载到内存,形成Class对象)
interfaces 代理类要实现的接口列表
h 指派方法调用的调用处理程序
InvocationHandler(java.lang.reflect. InvocationHandler):调用处理器接口,自定义了一个invoke方法,用于处理在动态代理类对象上的方法调用,一般在该方法实现对委托类的代理访问。(代理对象的所有方法都会调用InvocationHandler的invoke()方法,但个别不执行,如getClass()方法)
InvocationHandler的invoke方法
动态代理实现步骤
实现InvocationHandler接口创建调用处理器,给Proxy类提供ClassLoader和代理接口类型的数组创建动态代理类,以调用处理器类型为参数,利用反射获取到动态代理类的构造函数,再以调用处理器对象为参数,利用动态代理类的构造函数创建动态代理类对象
public class ProxyDmeo {
@Test
public void fun() {
/*三大参数 方法需要生成一个类 这个类实现了A B接口 然后创建这个类的对象 需要生成一个类 这个类需要ClassLoader加载到方法区中*/
ClassLoader loader = this.getClass().getClassLoader();
//2 Class[] interfaces 实现的接口数组
InvocationHandler h = new InvocationHandler() {//调用处理器
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理");
return null;
}
};
//根据三大参数创建动态代理对象
Object o=Proxy.newProxyInstance(loader, new Class[] {A.class,B.class}, h);
A a = (A) o; //可以强转成A和B类型
B b = (B) o;
a.a();
b.b();
System.out.println(o.getClass().getName());
System.out.println(Proxy.isProxyClass(o.getClass()));
}
}
interface A{
public void a();
}
interface B{
public void b();
}
运行结果
其中上面的类名可看出Java动态代理机制的特点之一,类名格式为"$ProxyN",其中N是一个逐一递增的数字,表示Proxy类第N次生成的动态代理类,并不是每一次调用Proxy的静态方法都会是这个值增加,因为如果对同一组接口试图重复创建动态代理类,它会返回前面已经创建好的代理类的类对象。
public Object invoke(Object proxy, Method method, Object[] args)
这个invoke()方法在调用代理对象所实现接口中的方法时调用,而不是在代理对象被创建时调用。
Object proxy:当前对象 即是代理对象
Method method:当前被调用的方法
Object[] args 实参
调用处理器 InvocationHandler
运行结果