动态代理:
- 代理设计模式:
使用一个代理将对象包装起来,然后用该代理对象取代原始对象.任何对原始对象的调用都要通过代理.代理对象决定是否以及何时将方法调用转到原始对象上.
eg: 上综艺(接口). 有艺人和经纪人,艺人为被代理类,经纪人为代理类.
静态代理中,厂家(接口)找艺人经纪人(Proxy、代理类)太麻烦,于是找到一个经纪人公司(ProxyFactory)帮忙找(动态实现).从而与艺人(被代理类)进行合作
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 生产代理类的类,首先要有一个需要代理的接口target,用target生成相对应的Proxy
* 利用方法为Proxy.newProxyInstance()
* 由于动态生成一个代理类,为了解决动态代理和接口、被代理者使用同一个方法,使用InvocationHandler中的invoke方法
*/
//综艺类
interface VarietyShow {
void sing();
void hold();
}
//电影厂家
interface Film {
void act();
}
//沈腾--演戏(implements)
class Shenteng implements Film {
@Override
public void act() {
System.out.println("沈腾演的喜剧很好笑");
}
}
//何炅--主持、唱歌(implements)
class Hejiong implements VarietyShow {
@Override
public void sing() {
System.out.println("何炅不是专业歌手");
}
@Override
public void hold() {
System.out.println("何炅是专业主持人");
}
}
//经纪人公司,负责找到对应艺人的经纪人
//动态代理,你想找谁的经纪人就匹配(生成)相对应的经纪人
class AgentFactory implements InvocationHandler{
private Object target;
public void setTarget(Object target) {
this.target = target;
}
public Object getProxy() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
}
//解决代理类和被代理类调用同一个方法问题,需要实现InvocationHandler(implements)
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(target,args);
return result;
}
}
public class Test {
public static void main(String[] args) {
//沈腾
Shenteng shenteng = new Shenteng();
//何炅
Hejiong hejiong = new Hejiong();
//经纪公司(代理类),帮忙找到对应艺人的经纪人
AgentFactory agentFactory = new AgentFactory();
//一家影片制作公司想找沈腾拍电影,他们需要找到沈腾的经纪人
agentFactory.setTarget(shenteng);
Film agentShen = (Film) agentFactory.getProxy();
//找到后与沈腾合作演戏
agentShen.act();
//一家综艺想找何炅主持节目,他们需要找到何炅的经纪人
agentFactory.setTarget(hejiong);
VarietyShow agentHe = (VarietyShow) agentFactory.getProxy();
//找到后与何炅合作主持节目
agentHe.hold();
}
}