代理模式介绍
代理模式的好处:
●可以是真实的角色的操作更加纯粹!不用去关注一些公共的业务
●公关也就交个代理角色!实现了业务的分工
●公共业务发生扩展的时候,方便集中管理
代理模式的缺点:
●一个真实角色就会产生一个代理角色;代码两会翻倍,开发效率会变低
静态代理
静态代理代码和理解:
可以将这个类理解为一个房东
* 房东因为生病急需用钱所以想将自己的房子快速租出去
* 但是,房东的资源比较少,想要及时将房子租出去需要花费时间,而自己需要马上去医院
* 所以将租房的工作代理给中介去执行
/*** 一个租房的接口* 该接口具有租房的方法(行为)*/
public interface IRentHouse {void rentHouse();
}
代理类:IntermediaryProxy
/**-* 理解:这个类类似中介* 我也可以进行租房的操作,我可以代理房东进行租房* 我可不白干,需要点中介费*/
public class IntermediaryProxy implements IRentHouse{private IRentHouse iRent ;public IntermediaryProxy(IRentHouse IRentHouse){this.iRent = IRentHouse;}@Overridepublic void rentHouse(){System.out.println("交1000中介费~~~我今天内将房子租出去");iRent.rentHouse();System.out.println("我把房子租出去了:给你钱,中介费给你扣了-1000");}
}
被代理类:RentHouse
/*** 代理模式* 可以将这个类理解为一个房东* 房东因为生病急需用钱所以想将自己的房子快速租出去* 但是,房东的资源比较少,想要及时将房子租出去需要花费时间,而自己需要马上去医院* 所以将租房的工作代理给中介去执行()**/
public class RentHouse implements IRentHouse{@Overridepublic void rentHouse(){System.out.println("实现租房");}
}
public class StaticTestMain {public static void main(String[] args){//模拟一个房东RentHouse landlord = new RentHouse();//模拟一个中介(代理将房租出去)IntermediaryProxy intermediaryProxy = new IntermediaryProxy(landlord);//执行租房的行为intermediaryProxy.rentHouse();}
}
动态代理
推荐视频:
狂神说的视频,对于动态代理讲解的很详细
记录一篇好的文章
java动态代理中的invoke方法是如何被自动调用的_zcc_0015的博客-CSDN博客
动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口--JDK动态代理
- 基于类的--cglib
- java字节码实现:javasist
以下为JDK动态代理
最重要的两个类:Proxy和InvocationHandler
Proxy的作用:提供创建动态代理类的和实例的静态方法
InvocationHandler:处理代理实例,并返回结果的
动态代理的好处:
- 可以是真实的角色的操作更加纯粹!不用去关注一些公共的业务
- 公关也就交个代理角色!实现了业务的分工
- 公共业务发生扩展的时候,方便集中管理
- 一个动态代理类代理的是一个接口,一般对应着一类业务
- 一个动态代理类可以代理多个类,只要实现了接口
/*** 一个租房的接口* 该接口具有租房的方法(行为)*/
public interface IRentHouse {void rentHouse();void needAgent(double money);
}
/*** 代理模式* 可以将这个类理解为一个房东* 房东因为生病急需用钱所以想将自己的房子快速租出去* 但是,房东的资源比较少,想要及时将房子租出去需要花费时间,而自己需要马上去医院* 所以将租房的工作代理给中介去执行()**/
public class RentHouse implements IRentHouse {@Overridepublic void rentHouse(){System.out.println("房东:支付的房租为:1000元!");System.out.println("实现租房");}@Overridepublic void needAgent(double money){System.out.println("房东内心os:没办法只能请中介");System.out.println("通过中介,获取的房租为:" + money+"元");}}
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
参数一:用于指定用哪个类加载器,去加载生成的代理类,一般为被代理的对象
参数二:指定接口,这些接口用指定生成的代理有哪些方法,通常也为被代理对象的接口
参数三:用来指定生成的代理对象要干什么事情
代理对象干什么事儿都由invoke()方法决定
官方的解释:处理代理实例,并且返回结果
public Object invoke(
Object proxy,
Method method,
Object[] args) throws Throwable
参数一:代理对象,注意是代理对象,不是被代理对象
参数二:代理类对象调用的方法,被封装为的方法对象。此方法也就作为了被代理类对象要调用的方法
参数三:代理对象调用方法时,传递的实际参数
代理类(使用动态代理实现):
public class DybanucTestMain {public static void main(String[] args){//模拟一个房东,被代理类RentHouse landlord = new RentHouse();//动态代理增强 landlord 对象/***我用动态代理,就不需要自己新建IntermediaryProxy(中介)对象,直接使用** 静态代理:有一个类文件来描述代理模式(此案例中就是IntermediaryProxy(中介)对象)* 动态代理:在内存中形成代理类** 三个参数:*ClassLoader loader = landlord.getClass().getClassLoader(), 类的加载器,是哪个需要代理的类,Class<?>[] interfaces = landlord.getClass().getInterfaces(), 被代理类的实现的接口InvocationHandler h = new InvocationHandler() {}:当我们通过代理类的对象,调用方法时,会自动的调用如下的方法:invoke()*/IRentHouse proxy_landlord = (IRentHouse) Proxy.newProxyInstance(landlord.getClass().getClassLoader(), landlord.getClass().getInterfaces(), new InvocationHandler() {/*****主要是用来实现代理逻辑**参数:proxy :代理对象* method:代理类对象调用的方法,被封装为的对象。此方法也就作为了被代理类对象要调用的方法* args :代理对象调用方法时,传递的实际参数*将被代理类要执行的方法a的功能就声明在invoke()中*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable{//使用真实对象调用该方法if(method.getName().equals("needAgent")){System.out.println("中介:来来来。嘿嘿!找我帮你出租呀,今天就给你租出去了,但是要给我中介费5%");double money = (double) args[0];money = money * 0.95;Object obj = method.invoke(landlord, money);return obj;}else {System.out.println("中介:你没让我帮你找,就不用中介费了");Object obj = method.invoke(landlord, args);return obj;}}});//模拟通过自己将房子租出去// proxy_landlord.rentHouse();//通过代理对象进行调用方法proxy_landlord.needAgent(1000);}
}