一、主要实现流程
1.
必须定义接口,里面定义一些行为,用来约束被代理对象和代理对象都要完成的事情。
2.
定义一个实现类实现接口,这个实现类的对象代表被代理的对象。
3.实现InvocationHandler接口,
实现代理需要handle的操作,一般包括
(1)前处理(例如开始计时)
(2)真正触发被代理对象的行为
(3)尾处理(例如结束计时)
4.
定义一个测试类,在里面创建被代理对象,然后为其创建一个代理对象返回。(重点)
5.
通过返回的代理对象进行方法的调用,观察动态代理的执行流程。
通过代理对象调用方法,执行流程:
- 先走向代理
- 代理中真正触发被代理对象的方法执行。
- 回到代理中,由代理负责返回结果给调用者。
优点
- 可以在不改变方法源码的情况下,实现对方法功能的增强,提高了代码的复用。
- 简化了编程工作、提高了开发效率,同时提高了软件系统的可扩展性。
- 可以为被代理对象的所有方法做代理。
- 非常的灵活,支持任意接口类型的实现类对象做代理,也可以直接为接本身做代理。
二、具体实现步骤
1.定义接口
被代理对象和代理对象都要完成的事情。
代理必须要帮忙完成,虽然真正sing的还是被代理的对象,但是“帮忙准备”和“帮忙收尾”也是“帮忙”。
// 定义接口
interface SingerService {
void sing(String song_name);
}
2.定义接口实现类
被代理帮助干某件事情,比如被助理帮忙的歌手。
// 实现该接口
class SingerServiceImpl implements SingerService {
public void Sing(String song_name) {
System.out.println("唱了一首歌:" + song_name);
}
}
3.实现InvocationHandler接口
主要是在invoke中实现代理要负责处理的事情,“代理操作1、2” 是代理核心的操作,可以在method方法的前后进行一些操作, 但method还是target执行,args是该方法需要的参数。
// 实现InvocationHandler接口
class MyInvocationHandler implements InvocationHandler {
// 声明一个私有变量,用来接上面的接口实现类
private Object target;
// 构造函数
public MyInvocationHandler(Object target) {
this.target = target;
}
// 实现InvocationHandler接口的invoke方法,该方法在代理对象调用方法时被触发。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理操作1");
Object result = method.invoke(target, args);
System.out.println("代理操作2");
return result;
}
}
4.实现代理
newProxyInstance()三个参数:
参数一:类加载器 加载代理类,产生代理对象。
参数二:真实业务对象的接口。(被代理的方法交给代理对象)
参数三:代理的核心处理程序。
public class ProxyTest {
public static void main(String[] args) {
// 创建目标对象(被代理的对象)
SingerService singerService = new SingerServiceImpl();
// 创建InvocationHandler实例(代理要处理的内容)
MyInvocationHandler handler = new MyInvocationHandler(singerService);
// 创建动态代理对象
SingerService proxy = (SingerService) Proxy.newProxyInstance(
singerService.getClass().getClassLoader(), //就这么写吧,类加载器
new Class[]{SingerService.getClass()}, //代理长啥样
handler //代理对象要干的事情
);
// 通过代理对象调用方法
proxy.sing("Where did you go");
}
}
handle可以在直接以匿名内部类形式书写,则无需步骤3.
感觉有点绕,先记个笔记再说。。