代理模式介绍
代理模式的好处:
●可以是真实的角色的操作更加纯粹!不用去关注一些公共的业务
●公关也就交个代理角色!实现了业务的分工
●公共业务发生扩展的时候,方便集中管理
代理模式的缺点:
●一个真实角色就会产生一个代理角色;代码两会翻倍,开发效率会变低
静态代理
静态代理代码和理解:
可以将这个类理解为一个房东
* 房东因为生病急需用钱所以想将自己的房子快速租出去
* 但是,房东的资源比较少,想要及时将房子租出去需要花费时间,而自己需要马上去医院
* 所以将租房的工作代理给中介去执行
java
/**
* 一个租房的接口
* 该接口具有租房的方法(行为)
*/
public interface IRentHouse {
void rentHouse();
}
代理类:IntermediaryProxy
java
/**-
* 理解:这个类类似中介
* 我也可以进行租房的操作,我可以代理房东进行租房
* 我可不白干,需要点中介费
*/
public class IntermediaryProxy implements IRentHouse{
private IRentHouse iRent ;
public IntermediaryProxy(IRentHouse IRentHouse)
{
this.iRent = IRentHouse;
}
@Override
public void rentHouse()
{
System.out.println("交1000中介费~~~我今天内将房子租出去");
iRent.rentHouse();
System.out.println("我把房子租出去了:给你钱,中介费给你扣了-1000");
}
}
被代理类:RentHouse
java
/**
* 代理模式
* 可以将这个类理解为一个房东
* 房东因为生病急需用钱所以想将自己的房子快速租出去
* 但是,房东的资源比较少,想要及时将房子租出去需要花费时间,而自己需要马上去医院
* 所以将租房的工作代理给中介去执行()
*
*/
public class RentHouse implements IRentHouse{
@Override
public void rentHouse()
{
System.out.println("实现租房");
}
}
java
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:处理代理实例,并返回结果的
动态代理的好处:
- 可以是真实的角色的操作更加纯粹!不用去关注一些公共的业务
- 公关也就交个代理角色!实现了业务的分工
- 公共业务发生扩展的时候,方便集中管理
- 一个动态代理类代理的是一个接口,一般对应着一类业务
- 一个动态代理类可以代理多个类,只要实现了接口
java
/**
* 一个租房的接口
* 该接口具有租房的方法(行为)
*/
public interface IRentHouse {
void rentHouse();
void needAgent(double money);
}
java
/**
* 代理模式
* 可以将这个类理解为一个房东
* 房东因为生病急需用钱所以想将自己的房子快速租出去
* 但是,房东的资源比较少,想要及时将房子租出去需要花费时间,而自己需要马上去医院
* 所以将租房的工作代理给中介去执行()
*
*/
public class RentHouse implements IRentHouse {
@Override
public void rentHouse()
{
System.out.println("房东:支付的房租为:1000元!");
System.out.println("实现租房");
}
@Override
public 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
参数一:代理对象,注意是代理对象,不是被代理对象
参数二:代理类对象调用的方法,被封装为的方法对象。此方法也就作为了被代理类对象要调用的方法
参数三:代理对象调用方法时,传递的实际参数
代理类(使用动态代理实现):
java
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()中
*/
@Override
public 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);
}
}