Java 动态代理笔记
本随笔为 《十分钟了解java动态代理》 笔记
代理模式
三要素:
- 接口:接口定义了服务要提供什么样的能力
- 提供服务的真实对象:一定要继承接口,来提供服务。别人不能直接访问这个对象,一定要通过代理去访问
- 代理对象:包含真实对象,从而操作真实主体对象,相当于访问者与真实对象的中介
两动作:
- 公共接口:真实对象和代理对象都必须同时继承同一个接口
- 代理对象必须包含真实的对象
动态代理
例子:
约妹子王美丽。由于我是一个正经人,因此不能直接去约她。要通过她的家人,征得同意后授权之下才能去联系王美丽。王美丽的家人就是王美丽的代理。
注意点:
- 客户端不能直接访问对象,一定要通过代理对象访问
- 动态:王美丽的家人有很多,谁有用找谁。
Java的动态代理
Proxy和InvocationHandler对象就组成了动态代理:
- Proxy
- 一个调度器:约王美丽的时候,联系她的家人,每个人不一定有时间,这个调度器总会找一个人来为你服务。
- InvocationHandler
- 是一个增强器:约王美丽,王美丽只看中颜值,只要小伙子颜值够了就跟他约会。但是王美丽的家人要对王美丽负责,所以小伙子约王美丽的时候,家人要做“增强”——事前调研一下小伙子有没有钱、房子、车,有没有离过婚;事后增强——约会干了些啥,问王美丽小伙子怎么样。
代码
三大要素之一:Girl
接口
public interface Girl {
void date();
void watchMovie();
}
实现类:WangMeiLi
public class WangMeiLi implements Girl {
@Override
public void date() {
System.out.println("王美丽说:跟你约会很开心!");
}
@Override
public void watchMovie() {
System.out.println("王美丽说:这个电影我不喜欢看。");
}
}
三大要素之一:动态代理对象 InvocationHandler
/**
* 增强器,只需要实现一个方法invoke(),业务就增强了
*/
public class WangMeiLiProxy implements InvocationHandler {
// 代理对象必须把真实提供服务对象RealSubject包含进来
// 代理是不能提供服务的,真正提供服务的是RealSubject
private Gril girl;
public WangMeiLiProxy(Girl girl) {
super();
this.girl = girl;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
doSomethingBefore(); // 前置增强
Object ret = method.invoke(girl, args); // Java 反射:调用 某个对象的方法,同时传递一些参数
doSomethingEnd(); // 后置增强
return ret;
}
public void doSomethingBefore() {
System.out.println("王美丽的父母说:我得先调查下这个男孩子的背景!");
}
public void doSomethingEnd() {
System.out.println("王美丽的父母说:他有没有对你动手动脚啊?");
}
// Proxy就是调度者
public Object getProxyInstance() {
// Proxy的核心静态方法newProxyInstance
// this -> InvocationHandler
return Proxy.newProxyInstance(girl.getClass().getClassLoader(), girl.getClass().getClassLoader().getInterfaces(), this);
}
}
调用者:Lison
public class Lison {
public static void main(String[] args) {
// 隔壁有个女孩,叫王美丽
Girl girl = new WangMeiLi();
// 她有一个庞大的家庭,想要跟她约会必须征得她家里人的同意
WangMeiLiProxy family = new WangMeiLiProxy(girl);
// 有一次我去约王美丽,碰到了她的妈妈,我征得了她妈妈的同意
// 即通过Proxy.newProxyInstance方法找出来一个人
Girl mother = (Girl) family.getProxyInstance();
// 通过她妈妈这个代理才能与王美丽约会
mother.date();
System.out.println("--------------------------------");
// 通过她的妈妈这个代理才能与王美丽看电影
mother.watchMovie();
}
}
执行结果:
王美丽的父母说:我得先调查下这个男孩子的背景!
王美丽说:跟你约会很开心!
王美丽的父母说:他有没有对你动手动脚啊?
--------------------------------
王美丽的父母说:我得先调查下这个男孩子的背景!
王美丽说:这个电影我不喜欢看。
王美丽的父母说:他有没有对你动手动脚啊?
对于王美丽来讲,她只关心Lison的颜值。但是对于她的父母(前、后置增强),要关心这个男孩子的所有情况。
上述结果类似于事务:开启事务—执行业务代码—提交事务。体现了动态代理是所有AOP类注解的本质!