一、概念
动态代理可以针对于一些不特定的类或者一些不特定的方法进行代理,我们可以在程序运行时动态的变化代理的规则,代理类在程序运行时才创建的代理模式成为动态代理。这种情况下,代理类并不是在Java代码中定义好的,而是在程序运行时根据我们的在Java代码中的“指示”动态生成的
Proxy 动态代理 是JDK动态代理,是基于接口来实现的。
二、代码实现
定义接口和实现类
public interface Dinner {
void eat(String foodName);
}
public class Person implements Dinner{
private String name;
public Person(String name) {
this.name = name;
}
public void eat(String foodName) {
System.out.println(name+"吃 "+foodName);
}
}
public class MyInvocationHandler implements InvocationHandler {
private Dinner dinner;
// 构造方法
public MyInvocationHandler(Dinner dinner){
this.dinner = dinner;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/**
* Object proxy 被代理对象
* Method method 被代理的方法
* Object[] args 被代理的方法,运行时的实参
*/
Object res = null;
if (method.getName().equals("eat")){
//增强方法
System.out.println("洗手");
//原有方法
res = method.invoke(dinner,args);
//增强方法
System.out.println("刷碗");
}else {
// 如果是其他方法,正常执行即可
res = method.invoke(dinner,args);
}
return res;
}
}
public class Client {
public static void main(String[] args) {
Dinner dinner = new Person("张三");
/**
* ClassLoader loader, 被代理的类加载器
* Class<?>[] interfaces, 被代理对象所实现的所有接口
* InvocationHandler h 执行处理器,专门用于定义规则
*/
ClassLoader loader = dinner.getClass().getClassLoader();
Class<?>[] interfaces = dinner.getClass().getInterfaces();
MyInvocationHandler invocationHandler = new MyInvocationHandler(dinner);
// 代理对象
Dinner dinnerProxy = (Dinner) Proxy.newProxyInstance(loader,interfaces,invocationHandler);
dinnerProxy.eat("包子");
}
}
三、总结
在不修改原有代码的基础之上,通过代理对象来增强相对应的方法,从而达到扩展的功能,同时 也满足了开闭原则,对扩展开放,对修改关闭。
JDK动态代理,一定要有接口和实现类的存在。代理对象只能增强接口中定义的方法 实现类中其他和接口无关的方法是无法增强的 。代理对象只能读取到接口中方法上的注解 不能读取到实现类方法上的注解