Java动态代理
动态代理
1.代理模式
为什么要有代理?生活中有很多这样的例子,比如,你要出去旅游,但是你又不想自己做攻略(要考虑交通、食宿、门票,太麻烦了,又浪费时间),那么就可以找家旅行社报团,它会帮你安排整个行程(带个手机拍照就可以了),这时候旅行社就是代理,你自己就是被代理对象。
代理模式:被代理者没有能力或者不愿意去完成某件事情,那么就需要找个人代替自己去完成这件事,这个人就是代理者,所以代理模式包含3个角色:被代理角色,代理角色,抽象角色(被代理角色和代理角色都需要遵守的协议)
2.代理模式-静态代理
定义旅行的接口
public interface Travel {
//旅游方法
public abstract void travel();
}
定义游客类,实现旅行接口
public class Tourist implements Travel{
//游客旅行
public void travel() {
System.out.println("张三去云南旅游...");
}
}
定义旅行社类,同样实现旅行接口,并且定义游客属性,通过构造函数初始化属性值
public class TravelAgency implements Travel {
private Tourist tourist; //定义游客属性
public TravelAgency(Tourist tourist) {
this.tourist = tourist;
}
//虽然还是游客旅行,但是前后有了旅行社的安排,很方便
public void travel() {
System.out.println("旅行社联系旅游巴士...");
tourist.travel(); //执行游客的旅行方法
System.out.println("旅行社安排吃饭住宿...");
}
}
定义测试类
@Test
public void method1() {
//创建游客对象
Tourist tourist = new Tourist();
//创建代理类旅行社对象,并传入游客参数
TravelAgency travelAgency = new TravelAgency(tourist);
//1. 不找代理
tourist.travel();
//2. 找代理
travelAgency.travel();
}
运行结果:
张三去云南旅游...
旅行社联系旅游巴士...
张三去云南旅游...
旅行社安排吃饭住宿...
在上面的例子中,分别扮演的角色:
TravelAgency-代理对象
Tourist-被代理类
Travel-抽象角色
所以,静态代理,代理类是真是存在的。
3.代理模式-动态代理
定义:动态代理就是直接通过反射生成一个代理对象,代理对象所属的类是不需要存在的。jdk提供一个Proxy类可以直接给实现接口类的对象直接生成代理对象
先举例:
public static void main(String[] args) {
final Tourist tourist = new Tourist();
Travel travel = (Travel) Proxy.newProxyInstance(Tourist.class.getClassLoader(), Tourist.class.getInterfaces(),
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("travel")){
System.out.println("旅行社联系旅游巴士...");
// 通过反射来调用被代理对象的方法
method.invoke(tourist);
System.out.println("旅行社安排吃饭住宿...");
}
return null;
}
});
travel.travel();
}
运行结果:
旅行社联系旅游巴士...
张三去云南旅游...
旅行社安排吃饭住宿...
3.1 Proxy类的Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法中参数解析:
-
Tourist.class.getClassLoader():被代理类的类加载器
-
Tourist.class.getInterfaces():被代理类所有实现的接口的Class对象
-
new InvocationHandler() { invoke() }:(接口)执行处理类
-
返回值: 代理对象
-
前2个参数是为了帮助在jvm内部生成被代理对象的代理对象,第3个参数,用来监听代理对象调用方法,帮助我们调用方法
3.2 InvocationHandler中的invoke(Object proxy, Method method, Object[] args)方法参数解析:
- proxy:代理对象(慎用)
- method:当前执行的方法
- args:当前执行的方法运行时传递过来的参数
- 返回值:当前方法执行的返回值
所以,动态代理,代理类是不真实存在的,但代理类是一定实现了被代理类的接口的