代理模式定义:是指一个类别可以作为其它东西的接口。代理者可以作任何东西的接口:网络连接、存储器中的对象、文件或其它昂贵或无法复制的资源。
举一个简单的例子:说现在有一家公司要拍古装电视剧有剧本,想要有流量就需要有明星参演,于是想要邀请胡歌参演,但是不能直接去找胡歌本人所以只能去找胡歌的经纪人谈关于签约参演的事情
代理模式角色:
1、抽象对象角色创建
package com.weather.spring.cloud.initializrstart.design.mode.proxy.staticproxy;
import java.util.Date;
/**
* @program: msa-weather-master
* @description: This is all star people service
* @author: W.HL
* @create: 2019-04-04 10:03
**/
public interface Star
{
/**
* star person name
*/
void starName();
/**
* person Performance
*/
void showTime(Date time);
}
2、具体对象角色创建
package com.weather.spring.cloud.initializrstart.design.mode.proxy.staticproxy;
import java.text.DateFormat;
import java.util.Date;
/**
* @program: msa-weather-master
* @description: Thi is HuGe class
* @author: W.HL
* @create: 2019-04-04 10:04
**/
public class HuGe implements Star
{
@Override
public void starName()
{
System.out.println("大家好! 我是胡歌");
}
/**
* person Performance
*/
@Override
public void showTime(Date time)
{
System.out.println("最近演出时间为:"+DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM).format(time));
}
}
3、代理对象角色创建
package com.weather.spring.cloud.initializrstart.design.mode.proxy.staticproxy;
import java.io.PrintStream;
import java.util.Date;
/**
* @program: msa-weather-master
* @description: Thi is agent person for star people
* @author: W.HL
* @create: 2019-04-04 10:11
**/
public class AgentPerson implements Star
{
private Star star;
public AgentPerson(Star star)
{
this.star = star;
}
/**
* star person name
*/
@Override
public void starName()
{
star.starName();
}
/**
* person Performance
*
* @param time
*/
@Override
public void showTime(Date time)
{
star.showTime(time);
}
public static void main(String[] args)
{
/*get the star*/
Star agentPerson = new AgentPerson(new HuGe());
agentPerson.starName();
agentPerson.showTime(new Date());
}
}
执行结果:
此为静态代理模式,
缺点:
1、如果代理对象里面的方法少的时候可以,但是如果里面很多方法呢?则都需要在代理对象中一一实现,造成了代码的冗余
2、如果这时候这个经纪人同时也是唐嫣的经纪人则代理人中的部分方法不能重复利用
于是对代理进行了升级变为动态代理,只改变代理本身其他保持不变
package com.weather.spring.cloud.initializrstart.design.mode.proxy.dynamicproxy;
import com.weather.spring.cloud.initializrstart.design.mode.proxy.staticproxy.HuGe;
import com.weather.spring.cloud.initializrstart.design.mode.proxy.staticproxy.Star;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Date;
/**
* @program: msa-weather-master
* @description: This is star dynamic proxy
* @author: W.HL
* @create: 2019-04-04 10:26
**/
public class AgentDynamicProxy implements InvocationHandler
{
private Object object;
public AgentDynamicProxy(Object object)
{
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
return method.invoke(object,args);
}
public static void main(String[] args)
{
/*获取代理对象*/
InvocationHandler invocationHandler = new AgentDynamicProxy(new HuGe());
/*创建动态代理对象*/
Star star = (Star) Proxy.newProxyInstance(new HuGe().getClass().getClassLoader(),new Class[]{Star.class},invocationHandler);
star.starName();
star.showTime(new Date());
}
}
InvocationHandler源码解析
通过实现java中提供的InvocationHandler接口然后使用反射机制来调用相应具体代理对象的方法
/**
* {@code InvocationHandler} is the interface implemented by
* the invocation handler of a proxy instance.
*
* Each proxy instance has an associated invocation handler.
* When a method is invoked on a proxy instance, the method
* invocation is encoded and dispatched to the {@code invoke}
* method of its invocation handler.
*
* @author Peter Jones
* @see Proxy
* @since 1.3
*/
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
解析:每个代理实例都有一个关联的调用处理程序。当在代理实例上调用方法时,则会被分配到其相应的实现的invoke中调用处理程序,所以如果想要调用其方法则需要在具体实现的invoke方法中通过传来的对象通过invoke找到其真正的方法
InvocationHandler源码中invoke方法解析
当执行到star.starName();继续执行的时候进入到invoke中,可以看到具体的代理对象以及具体的代理方法
newProxyInstance方法源码解析
newProxyInstance(ClassLoader loader,Class>[] interfaces,InvocationHandler h)
* @param loader the class loader to define the proxy class
* @param interfaces the list of interfaces for the proxy class
* to implement
* @param h the invocation handler to dispatch method invocations to
* @return a proxy instance with the specified invocation handler of a
* proxy class that is defined by the specified class loader
* and that implements the specified interfaces
* @throws IllegalArgumentException if any of the restrictions on the
动态代理通过反射机制很好的实现代理可以重复调用重复使用,可以在不修改原来代码的基础上添加新特性比如新增话剧、演唱会、舞蹈等