动态代理实战
动态代理它可以直接给某一个目标(被代理 对象)对象(实现了某个或者某些接口)生成一个代理对象,而不需要代理类存在。
动态代理与代理模式原理是一样的,只是它没有具体的代理类,直接通过反射生成了一个代理对象。
jdk中的动态代理
1、Java.lang.reflect.Proxy类可以直接生成一个代理对象
Proxy.newProxyInstance方法参数介绍
ClassLoader:类加载器
它是用来加载器的,把.class文件加载到内存,形成Class对象!
Class[] interfaces:指定要实现的接口们
InvocationHandler:代理对象的所有方法(个别不执行,getClass())都会调用InvocationHandler的invoke()方法。
2、InvocationHandler方法参数介绍
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
这个invoke()方法在什么时候被调用!在调用代理对象所实现接口中的方法时
Object proxy:当前对象,即代理对象!在调用谁的方法!
Method method:当前被调用的方法(目标方法)
Object[] args:实参!
示例一:
Customer类为需要打官司的顾客,Lawyer为律师类,Lawyer类需要代理Customer打官司。
定义代理类与目标类共同的接口:
interface Law {
//定义一个打官司的接口,需要实现打官司
void law();
}
被代理类:某个客户需要打官司
class Customer implements Law {
@Override
public void law() {
System.out.println("上法庭陈述事实");
}
}
创建实现动态代理的MyHandler类,实现InvocationHandler接口和invoke方法。
/**
* 实现动态代理的核心接口,动态代理本质采用的java反射机制实现
*/
class MyHandler implements InvocationHandler {
private Customer customer;
public MyHandler(Customer customer) {
this.customer = customer;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("搜集证据");
Object obj = method.invoke(customer, args); //使用反射调用customer中的method方法
System.out.println("打赢官司");
return obj;
}
}
执行测试:
public static void main(String[] args) {
//代理目标对象
Customer customer = new Customer();
//代理回调类
MyHandler myHandler = new MyHandler(customer);
//生成代理对象Proxy通过调用newProxyInstance方法生成代理对象,传入该类的classLoader,实现接口,InvocationHandler
Law proxy = (Law) Proxy.newProxyInstance(Customer.class.getClassLoader(), customer.getClass().getInterfaces(), myHandler);
proxy.law();
}
调用结果:
示例二:
定义代理类与目标类共同的接口:
public interface HelloInterface {
void sayHello();
}
被代理类:
class Hello implements HelloInterface {
@Override
public void sayHello() {
System.out.println("这里是被代理类Hello");
}
}
创建实现动态代理的ProxyHandler类,实现InvocationHandler接口和invoke方法。
class ProxyHandler implements InvocationHandler {
private Object object;
//需要传入Object类型,任意类型
public ProxyHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//invoke中使用反射调用传入的被代理对象的方法
System.out.println("before invoke" + method.getName());
method.invoke(object, args);
System.out.println("after invoke" + method.getName());
return null;
}
}
执行测试:
public static void main(String[] args) {
HelloInterface hello = new Hello(); //创建需要被代理的Hello类对象
//此时,不再创建具体的代理对象,而是用Proxy.newProxyInstance利用反射生成代理对象
InvocationHandler invocationHandler = new ProxyHandler(hello);
//通过Proxy类的静态方法newProxyInstance返回一个接口的代理实例(注,这里需要强转)。针对不同的代理类,传入相应的代理程序控制器InvocationHandler。
//newProxyInstance需传入三个参数:分别传入被代理对象的classloader、interface,和创建的invocationHandler,
HelloInterface proxyHello = (HelloInterface) Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), invocationHandler);
proxyHello.sayHello(); //通过调用代理接口的方法,调用到了invocationHandler的invoke方法,从而调用到了被代理对象的方法
}
调用结果:
动态代理比静态代理优秀的方法在于,可以动态地代理各个被代理类,那么此时新的代理类就来了。
创建新的代理类Bye:
public interface ByeInterface {
void sayBye();
}
class Bye implements ByeInterface {
@Override
public void sayBye() {
System.out.println("这里是被代理类Bye");
}
}
重新执行:
public static void main(String[] args) {
HelloInterface hello = new Hello(); //创建需要被代理的Hello类对象
ByeInterface bye = new Bye();
//此时,不再创建具体的代理对象,而是用Proxy.newProxyInstance利用反射生成代理对象
InvocationHandler invocationHandler = new ProxyHandler(hello);
InvocationHandler byeHandler = new ProxyHandler(bye);
//通过Proxy类的静态方法newProxyInstance返回一个接口的代理实例(注,这里需要强转)。针对不同的代理类,传入相应的代理程序控制器InvocationHandler。
//newProxyInstance需传入三个参数:分别传入被代理对象的classloader、interface,和创建的invocationHandler,
HelloInterface proxyHello = (HelloInterface) Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), invocationHandler);
proxyHello.sayHello(); //通过调用代理接口的方法,调用到了invocationHandler的invoke方法,从而调用到了被代理对象的方法
ByeInterface proxyBye = (ByeInterface) Proxy.newProxyInstance(bye.getClass().getClassLoader(), bye.getClass().getInterfaces(), byeHandler);
proxyBye.sayBye();
}
执行结果:
动态代理具体步骤:
通过实现 InvocationHandler 接口创建自己的调用处理器;
通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。