代理
什么是代理?
为什么要使用代理?
- 在程序设计中有一个类的单一性原则问题,这个原则很简单,就是每个类的功能尽可能单一。为什么要单一,因为只有功能单一这个类被改动的可能性才会最小。
例如:转账模块,money转入传出业务。 但是完整的系统还要考虑权限、 记录流水号、打印日志。 只有某些用户支持外币转账 才可以调用外币转账这个类。 需要声明这个类的代理类处理:记录流水 打印日志 控制权限的功能。 让业务和系统功能分开,各司其职 ,开发只需关注自己的业务功能。 - 对已有的系统添加一些功能特性,但又不希望对原有的代码进行修改时。
修改原系统的各模块,在调用接口的地方加代码
优点:简单直接,想怎么加就怎么加
缺点:需要对原系统的每个模块都进行改动,与需求3有很大的冲突
使用Spring AOP,通过配置的方式动态加代码
优点:实现比较简单,对原系统的改动也比较少
缺点:对没有采用Spring技术的模块就没办法了
静态代理
用继承实现 :代理类继承目标类 (代理对象和目标对象是父子关系,代理对象是子类,目标对象是父)
用接口实现: 目标对象类和代理对象类实现同一个接口,2. 代理对象当中必须包含目标对象
用继承实现:
转账业务接口
package com.chuliuhuan.proxy;
/**
* @author chuliuhuan
* @date 2021-06-03 13:35
*/
public interface Transfer {
/**
* 转入
* @return -1 转账失败,1 转账成功
*/
public int transferIn(double outAccount, double inAccount , double transferMoney );
/**
* 转出
* @return -1 转账失败,1 转账成功
*/
public int transferOut(double outAccount, double inAccount , double transferMoney );
}
定期转账java类
package com.chuliuhuan.proxy;
/**
* @author chuliuhuan
* @date 2021-06-03 13:40
*/
public class FixDateTransfer implements Transfer{
/**
只关注 转账业务
*/
@Override
public int transferIn(double outAccount, double inAccount , double transferMoney ) {
if ((outAccount > transferMoney)) {
outAccount= outAccount - transferMoney ;
inAccount = inAccount + transferMoney;
return 1;
}else {
System.out.println("转账失败!没有那么多钱可以扣除" );
return -1;
}
}
@Override
public int transferOut(double outAccount, double inAccount , double transferMoney ) {
if ((outAccount > transferMoney)) {
outAccount= outAccount - transferMoney ;
inAccount = inAccount + transferMoney;
return 1;
}else {
return -1;
}
}
}
定期转账代理类:
package com.chuliuhuan.proxy;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author chuliuhuan
* @date 2021-06-03 13:42
*/
public class TransferProxy extends FixDateTransfer{
public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public int transferIn(double outAccount, double inAccount , double transferMoney ) {
// 转账业务前日志打印
System.out.println( dateFormat.format(new Date(System.currentTimeMillis()))+ " "+ this.getClass().getName()+ ".transferIn , request params is { outAccount : "+outAccount+ ",inAccount:"+inAccount +",transferMoney:"+transferMoney +"} begin");
int result = super.transferIn(outAccount,inAccount,transferMoney);
// 转账业务结束后日志打印
System.out.println(dateFormat.format(new Date(System.currentTimeMillis()))+ " " + this.getClass().getName()+ ".transferIn , request params is { outAccount : "+outAccount+ ",inAccount:"+inAccount +",transferMoney:"+transferMoney +"} end");
return result;
}
}
代理类测试使用:
package com.chuliuhuan.test;
import com.chuliuhuan.proxy.TransferProxy;
/**
* @author chuliuhuan
* @date 2021-06-03 14:14
*/
public class FixDateTransferTest {
public static void main(String[] args) {
TransferProxy fixDateTransfer = new TransferProxy();
fixDateTransfer.transferIn(300000,1000,20000);
fixDateTransfer.transferIn(300000,1000,30000000);
}
}
运行结果:
C:\Users\哈哈\.jdks\adopt-openjdk-1.8.0_292\bin\java.exe ...
2021-06-03 14:28:38 com.chuliuhuan.proxy.TransferProxy.transferIn , request params is { outAccount : 300000.0,inAccount:1000.0,transferMoney:20000.0} begin
2021-06-03 14:28:38 com.chuliuhuan.proxy.TransferProxy.transferIn , request params is { outAccount : 300000.0,inAccount:1000.0,transferMoney:20000.0} end
2021-06-03 14:28:38 com.chuliuhuan.proxy.TransferProxy.transferIn , request params is { outAccount : 300000.0,inAccount:1000.0,transferMoney:3.0E7} begin
转账失败!没有那么多钱可以扣除
2021-06-03 14:28:38 com.chuliuhuan.proxy.TransferProxy.transferIn , request params is { outAccount : 300000.0,inAccount:1000.0,transferMoney:3.0E7} end
Process finished with exit code 0
继承实现静态代理缺点:系统有100个目标类,就要100个代理类。 多个业务类要分别继承处理,工作量多。 代理类和目标类内部结构一致。
用接口实现:
目标对象类和代理对象类实现同一个接口,还是用转账的场景做例子
转账接口
package com.chuliuhuan.proxy;
/**
* @author chuliuhuan
* @date 2021-06-03 13:35
*/
public interface Transfer {
/**
* 转入
* @return -1 转账失败,1 转账成功
*/
public int transferIn(double outAccount, double inAccount , double transferMoney );
/**
* 转出
* @return -1 转账失败,1 转账成功
*/
public int transferOut(double outAccount, double inAccount , double transferMoney );
}
目标类:
package com.chuliuhuan.proxy;
/**
* @author chuliuhuan
* @date 2021-06-03 21:26
*/
public class RealTimeTransfer implements Transfer{
@Override
public int transferIn(double outAccount, double inAccount, double transferMoney) {
if ((outAccount > transferMoney)) {
outAccount= outAccount - transferMoney ;
inAccount = inAccount + transferMoney;
return 1;
}else {
System.out.println("转账失败!没有那么多钱可以扣除" );
return -1;
}
}
@Override
public int transferOut(double outAccount, double inAccount, double transferMoney) {
if ((outAccount > transferMoney)) {
outAccount= outAccount - transferMoney ;
inAccount = inAccount + transferMoney;
return 1;
}else {
System.out.println("转账失败!没有那么多钱可以扣除" );
return -1;
}
}
}
代理类:
package com.chuliuhuan.proxy;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author chuliuhuan
* @date 2021-06-03 21:29
*/
public class TransferProxy implements Transfer{
public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private Transfer transfer;
public TransferProxy(Transfer transfer) {
this.transfer = transfer;
}
@Override
public int transferIn(double outAccount, double inAccount, double transferMoney) {
System.out.println( dateFormat.format(new Date(System.currentTimeMillis()))+ " "+ this.getClass().getName()+ ".transferIn , request params is { outAccount : "+outAccount+ ",inAccount:"+inAccount +",transferMoney:"+transferMoney +"} begin");
int result = transfer.transferIn(outAccount, inAccount, transferMoney);
System.out.println( dateFormat.format(new Date(System.currentTimeMillis()))+ " "+ this.getClass().getName()+ ".transferIn , request params is { outAccount : "+outAccount+ ",inAccount:"+inAccount +",transferMoney:"+transferMoney +"} end");
return result;
}
@Override
public int transferOut(double outAccount, double inAccount, double transferMoney) {
System.out.println( dateFormat.format(new Date(System.currentTimeMillis()))+ " "+ this.getClass().getName()+ ".transferIn , request params is { outAccount : "+outAccount+ ",inAccount:"+inAccount +",transferMoney:"+transferMoney +"} begin");
int result = transfer.transferOut(outAccount, inAccount, transferMoney);
System.out.println( dateFormat.format(new Date(System.currentTimeMillis()))+ " "+ this.getClass().getName()+ ".transferIn , request params is { outAccount : "+outAccount+ ",inAccount:"+inAccount +",transferMoney:"+transferMoney +"} end");
return result;
}
}
测试类:
package com.chuliuhuan.test;
import com.chuliuhuan.proxy.RealTimeTransfer;
import com.chuliuhuan.proxy.TransferProxy;
/**
* @author chuliuhuan
* @date 2021-06-03 21:46
*/
public class TransferProxyTest {
public static void main(String[] args) {
RealTimeTransfer realTimeTransfer= new RealTimeTransfer();
TransferProxy proxy= new TransferProxy(realTimeTransfer);
proxy.transferIn(300000,1000,30000000);
}
}
也是可以打印出想要的结果:
2021-06-03 22:33:00 com.chuliuhuan.proxy.TransferProxy.transferIn , request params is { outAccount : 300000.0,inAccount:1000.0,transferMoney:3.0E7} begin
转账失败!没有那么多钱可以扣除
2021-06-03 22:33:00 com.chuliuhuan.proxy.TransferProxy.transferIn , request params is { outAccount : 300000.0,inAccount:1000.0,transferMoney:3.0E7} end
Process finished with exit code 0
接口静态代理优点是: 在不修改目标对象的功能前提下,对目标功能扩展。
接口静态代理缺点是:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多 。同时,一旦接口增加方法,目标对象与代理对象都要维护. (可以使用动态代理
)