代理模式的定义:被代理者没有能力或者不愿意去完成某件事,那么就需要找别人代替自己去完成某件事,这个别人就是代理者,所以代理模式有三个角色:被代理角色,代理角色,抽象角色(协议)
拿一手房东和二手房东打比方,一手房东有想把房子租出去的想法,二手房东也有想把房子租出去的想法。但是一般租客不是很容易找到一手房东。租客找二手房东租房子,并不知道一手房东是谁,二手房东可以在房子里面增加家具啥的,来提高房价。
静态代理案例
抽象角色(协议)
public interface Chuzu {
//出租房子的想法,出租多少钱
abstract int chuzufangzi();
}
被代理者
public class Fangzi implements Chuzu{
@Override
public int chuzufangzi() {
//一手房东只需要500一个月就把房子出租
return 500;
}
}
代理者,这里是静态代理,如果把Fangzi换成接口,那么就可以代理各种房子
public class DaiFangzi implements Chuzu{
private Fangzi fangzi;
public DaiFangzi(Fangzi fangzi) {
this.fangzi = fangzi;
}
@Override
public int chuzufangzi() {
int chuzufangzi = fangzi.chuzufangzi();
//二手房东加价500
return chuzufangzi+500;
}
}
静态代理和动态代理的区别:
静态代理模式:代理类是实际存在的
动态代理模式:代理类是不存在的,直接动态生成一个代理对象
JDK动态代理的实现案例
Proxy类
public class Test {
/**
* 动态代理模式:
* JDK提供了一个Proxy类,可以给实现接口类的对象,直接生成一个代理对象
* public static Object newProxyInstance(ClassLoader loader,
* Class<?>[] interfaces,
* InvocationHandler h)
* 参数一:被代理类的类加载器
* 参数二:被代理类实现的所有接口的字节码对象
* 参数一和参数二是为了帮助生成代理对象
* 参数三:InvocationHandler是一个接口,里面有一些回调函数
* 参数三用来监听代理对象调用方法
* InvocationHandler是一个接口接口中的方法,调用代理类的任何方法,此方法都会调用
* public Object invoke(Object proxy, Method method, Object[] args)
* 参数一:代理对象,一般不用
* 参数二:代理对象调用的方法
* 参数三:代理对象调用方法的实际参数
*/
public static void main(String[] args) {
//被代理类对象
Fangzi fangzi = new Fangzi();
Class<Fangzi> fangziClass = Fangzi.class;
//获取被代理类的类加载器
ClassLoader classLoader = fangziClass.getClassLoader();
//获取被代理类实现的所有接口
Class<?>[] interfaces = fangziClass.getInterfaces();
//生成的是接口的实现类对象,多态
Chuzu o = (Chuzu)Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
int invoke = (int)method.invoke(fangzi);
//二手房东增加500元
return invoke+500;
}
});
int chuzufangzi = o.chuzufangzi();
System.out.println(chuzufangzi);
}
}