静态代理
静态代理是在编译时就将接口、实现类、代理类一股脑儿全部手动完成。
静态代理的实现步骤
一:创建公共接口(通用)
/**
* 顾客通用行为接口
*
* @author wangmaoyu
* @create 2018-02-24 23:48
**/
public interface ICustomer {
/**
* 吃
* @param s
*/
void eat(String s);
/**
* 喝
* @param s
*/
void drink(String s);
/**
* 支付
* @param d
*/
void pay(double d);
}
二:具体实现类
/**
* 顾客实现类(用于实现动态代理)
*
* @author wangmaoyu
* @create 2018-02-24 23:49
**/
public class Customer implements ICustomer{
@Override
public void eat(String s) {
System.out.println("顾客要吃一个15元的"+s);
}
@Override
public void drink(String s) {
System.out.println("顾客要喝一杯6元的"+s);
}
@Override
public void pay(double d) {
System.out.println("顾客一共消费"+d);
}
}
三:代理实现类
/**
* 静态代理实现类
*
* @author wangmaoyu
* @create 2018-02-25 16:02
**/
public class CustomerProxy implements ICustomer {
private Customer customer;
public CustomerProxy(Customer customer) {
this.customer = customer;
}
@Override
public void eat(String s) {
customer.eat(s);
}
@Override
public void drink(String s) {
customer.drink(s);
}
@Override
public void pay(double d) {
customer.pay(d);
}
public static void main(String[] args) {
CustomerProxy proxy=new CustomerProxy(new Customer());
proxy.eat("汉堡");
proxy.drink("可乐");
proxy.pay(21);
}
}
实现效果:
顾客要吃一个15元的汉堡
顾客要喝一杯6元的可乐
顾客一共消费21.0
图解:
代理模式的原理:通过代理对象操作真实对象,进行一层封装。
优点:扩展原有功能,不侵入代码。
缺点:真实对象有多少个就要写多少个代理对象。或者只单独创建一个代理对象的话,就得需要创建多个接口和多个真实对象。
显然这种方式,工作量是巨大的。
动态代理
搞清楚静态代理的缺点十分重要,因为动态代理的目的就是为了解决静态代理的缺点。通过使用动态代理,我们可以通过在运行时,动态生成一个持有RealObject、并实现代理接口的Proxy,同时注入我们相同的扩展逻辑。哪怕你要代理的RealObject是不同的对象,甚至代理不同的方法,都可以动过动态代理,来扩展功能。
动态代理是通过实现InvocationHandler 接口来实现的。这个Handler中的invoke方法中实现了代理类要扩展的公共功能。
实现代码:
/**
* 动态代理实现类
*
* @author wangmaoyu
* @create 2018-02-24 23:53
**/
public class DynamicProxy implements InvocationHandler {
//用于接收具体实现类的实例对象
private Object realObj;
public DynamicProxy(Object realObj) {
this.realObj = realObj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
method.invoke(realObj,args);
return null;
}
public static void main(String[] args) {
ICustomer realObject=new Customer();
// ICustomer proxy= (ICustomer) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{ICustomer.class},new DynamicProxy(realObject));
ICustomer proxy= (ICustomer) Proxy.newProxyInstance(ICustomer.class.getClassLoader(),new Class[]{ICustomer.class},new DynamicProxy(realObject));
proxy.eat("汉堡");
proxy.drink("可乐");
proxy.pay(21);
}
}
实现效果一样,略。
Proxy.newProxyInstance 传入的是一个ClassLoader, 一个代理接口,和我们定义的handler,返回的是一个Proxy的实例。
代理三要素:真实对象:RealObject,代理接口:Action,代理实例:Proxy。