1.静态代理
什么是代理模式?
代理模式的定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。举例说明,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用。
应用场景举例:通过上面的代理模式描述我们可以知道,其目的就是为了控制对象引用,生活场景中我们以买车为例,如果我们要买一辆轿车必须通过汽车4S店,汽车4s店就是充当代理角色,其目的就是控制买车客户的买车行为,必须通过汽车4S店才能从汽车厂商买一辆车。
public interface IBuyCar {
void buyCar(int price);
}
---------------
public class Customer implements IBuyCar {
private int cash;
@Override
public void buyCar(int price) {
System.out.println("buyCar"+" 花了这么多钱:"+price+" $");
this.cash = cash -price;
}
public int getCash() {
return cash;
}
public void setCash(int cash) {
this.cash = cash;
}
}
==============================================
public class Proxy4s implements IBuyCar {
private Customer customer;
public Proxy4s(Customer cs){
this.customer = cs;
}
@Override
public void buyCar(int price) {
if(customer.getCash()>=price)
this.customer.buyCar(price);
else
System.out.println("不够钱买车~ 撤销");
}
public static void main(String[] args) {
Customer cs = new Customer();
cs.setCash(120000);
Proxy4s s4 = new Proxy4s(cs);
s4.buyCar(128000);
System.out.println("customer 还剩余:"+cs.getCash());
}
}
通过代理模式实现权限控制 通过上面的例子,我们可能有个疑问,难道就不能直接去厂家买车吗?当然可以,如果在使用场景中实现类能满足要求时,我们当然可以直接实现类,但当实现类不能满足要求,要扩展需求,根据开闭原则你又不能修改实现类代码,这时你就用代理类。比如购买一辆车我们要对客户进行一个购车款审核,如果符合条件就买车,不符合要求我们就告知客户购车款不足。
2.动态代理模式:
public class DynamicProxy implements InvocationHandler {
Object object;
public DynamicProxy(Object obj) {
this.object = obj;
}
/** 覆盖InvocationHandler接口中的invoke()方法
* 更重要的是,动态代理模式可以使得我们在不改变原来已有的代码结构
* 的情况下,对原来的“真实方法”进行扩展、增强其功能,并且可以达到
* 控制被代理对象的行为,下面的before、after就是我们可以进行特殊
* 代码切入的扩展点了。
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
Object result = method.invoke(this.object, args);
return result;
}
public static void main(String[] args) {
Customer cs = new Customer();
InvocationHandler handler = new DynamicProxy(cs);
/** 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数
* 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象
* 第二个参数customer.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了
* 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
**/
IBuyCar buyCar = (IBuyCar) Proxy.newProxyInstance(handler.getClass().getClassLoader(),
cs.getClass().getInterfaces(),
handler);
buyCar.buyCar(118000);
}
}