静态代理
角色分析:
- 抽象角色︰一般会使用接口或者抽象类来解决
- 真实角色︰被代理的角色
- 代理角色︰代理真实角色,代理真实角色后,我们一般会做一些附属操作。
- 客户: 访问代理对象的人
代理模式的好处:
- 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
- 公共也就就交给代理角色!实现了业务的分工!
- 公共业务发生扩展的时候,方便集中管理!
缺点:
- 一个真实角色就会产生一个代理角色;代码量会翻倍开发效率会变低
代码步骤:
- 接口
- 真实角色
- 代理角色
- 客户端访问代理角色
样例
接口
public interface Rent {
void rent();
}
真实角色
public class Host implements Rent{//真实角色实现接口
@Override
public void rent() {
System.out.println("房东要出租房屋。。。");
}
}
代理角色
public class Proxy implements Rent{
private Host host;
public Proxy(Host host) {
this.host = host;
}
public Proxy() {
}
@Override
public void rent() {//代理Host
host.rent();
}
public void extend01(){
System.out.println("在代理真实角色的基础上扩展业务.。。01");
}
public void extend02(){
System.out.println("在代理真实角色的基础上扩展业务。。。02");
}
public void extend03(){
System.out.println("在代理真实角色的基础上扩展业务。。。03");
}
}
客户端访问代理角色
public class Client {
public static void main(String[] args) {
Proxy proxy=new Proxy(new Host());
proxy.rent();//通过代理使用Host的方法
proxy.extend01();
proxy.extend02();
proxy.extend03();
}
}
动态代理
根据如上的介绍,你会发现每个代理类只能为一个接口服务,这样程序开发中必然会产生许多的代理类 所以我们就会想办法可以通过一个代理类完成全部的代理功能,那么我们就需要用动态代理
在上面的示例中,一个代理只能代理一种类型,而且是在编译器就已经确定被代理的对象。而动态代理是在运行时,通过反射机制实现动态代理,并且能够代理各种类型的对象
在Java中要想实现动态代理机制,需要java.lang.reflect.InvocationHandler
接口和 java.lang.reflect.Proxy
类的支持
- 动态代理和静态代理角色一样
- 动态代理的代理类是动态生成的,不是我们直接写好的!
- 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口---JDK动态代理【我们在这里使用】
- 基于类: cglib
- java字节码实现: javasist
JDK动态代理
-
动态代理的表现形式即同一个代理对象可以代理多个被代理对象,不再像之前的静态代理仅约束于一个被代理对象。
-
在java中,基于JDK的代理类和被代理类,必须实现同一个接口。
样例
- 接口
public interface Business {
void doBusiness();
}
- 真实对象(多个类实现同一个接口)
public class Boss01 implements Business{
public void doBusiness() {
System.out.println("老板1号在谈生意");
}
public void aVoid(){
System.out.println("dfgdgssdfg");
}
}
public class Boss02 implements Business{
public void doBusiness() {
System.out.println("老板2号在谈生意");
}
}
public class Boss03 implements Business{
@Override
public void doBusiness() {
System.out.println("老板3号在谈生意");
}
}
- 实现
InvocationHandler
接口
public class ProxyIH implements InvocationHandler {//
private Object target;//真实对象(被代理的对象)
public void setTarget(Object target) {//设置真实对象
this.target = target;
}
public Object getTarget(){//获取具体被代理的真实对象
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {//该方法可以实现业务扩展,以及执行被代理对象的方法
extend();
Object result = method.invoke(target,args);
log(target.getClass().getName());
return result;
}
public void extend(){
System.out.println("代理扩展业务:展示老板动态");
}
public void log(String msg){
System.out.println("代理了"+msg+"的业务");
}
}
- test(Client)
动态代理,代理的是接口
public class Client {
public static void main(String[] args) {
ProxyIH proxyIH = new ProxyIH();
proxyIH.setTarget(new Boss01());
// proxyIH.setTarget(new Boss02());
// proxyIH.setTarget(new Boss03());
Business business = (Business) proxyIH.getTarget();//动态代理,代理的是接口
business.doBusiness();
}
}