》 初识 代理模式
1.代理模式
概念: 为真实对象提供一层代理
本质: 保护真实对象
分类 :
概念分类: 静态代理 动态代理
功能分类: 虚代理 远程代理(RMI) copy-on-write 保护代理 Cache代理 防火墙代理 同步代理 智能指引
静态代理 : 有一个中间类,用来调用真实对象,测试类调用该类
// 静态代理演示
// 真实对象
private PersonRun pr = new KgcInstall();
@Override
public void run() {
// 判断一下让真是对象跑步的是谁
// if(如果是教练)
pr.run();
// if(如果不是教练)
// 返回 抱歉,您没有权限让真实对象跑步
}
缺点: 修改和新增 真实对象时会产生大量的冗余工作量
动态代理: 使用了反射的技术
实现步骤:
1、 实现Invocation
2、创建目标对象
3、将目标对象与代理对象进行关联
4、使用目标对象调用对应的方法
public class DynamicProxy implements InvocationHandler {
// 真实对象
private Object obj;
public Object getProxy(Object objArgs){
// 传入真实对象
this.obj = objArgs;
// 创建一个代理对象返回给客户端调用
// 将代理对象与真实对象进行关联
Object proxyObj = Proxy.newProxyInstance(
objArgs.getClass().getClassLoader(),
objArgs.getClass().getInterfaces(),
this);
return proxyObj;
}
@Override
// 调用方法 代理对象 待执行方法 参数列表
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 方法调用之前
System.out.println("方法调用之前");
// 协助调用真实对象里的方法
Object resultObj = method.invoke(obj, args);
// 方法调用之后
System.out.println("方法调用之后");
return resultObj;
}
}
调用 getProxy() 的方法,获取对象
// 演示动态代理调用
// 获取真实对象
PersonRun pr = new KgcInstall();
DynamicProxy dp = new DynamicProxy();
// 将真实对象传入动态代理,并生成对应的代理对象
PersonRun proxyPr = (PersonRun)dp.getProxy(pr); //只能代理接口
proxyPr.run();
缺点: 只能代理接口
2.CGLIB
概念 :实现动态代理
底层 是 : 1. ASM
2.CGLIB 是通过创建目标对象的子类的形式来进行拦截和处理
(CGLIB 不能处理final 对象)
使用 步骤:
1.引入CGLIB 的 jar 包
2.实现methodInterceptor接口
3.获取目标对象
4.创建代理对象 : Enhancer : 1.superClass 2.callback 3.Enhancer.create
5.使用目标对象调用对应的方法
public class CglibProxy implements MethodInterceptor {
// 需要一个被代理对象(目标对象)
private Object target;
// 传入目标对象
public CglibProxy(Object target){
this.target = target;
}
// 返回客户一个代理对象
public Object getProxy(){
Enhancer e = new Enhancer();
// CGLIB 会创建一个目标对象的子对象,通过反射对父对象的内容进行拦截和处理
e.setSuperclass(target.getClass());
e.setCallback(this);
// 创建代理对象
return e.create();
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy methodProxy) throws Throwable {
System.out.println(" CGLIB - 方法调用之前");
// 使用目标对象进行方法调用
Object result = methodProxy.invoke(target,arg2);
System.out.println(" CGLIB - 方法凋用之后");
return result;
}
}
注意: 这边是 new 对象时,调用有参构造函数 将对象 传入,其实跟上面 那个 动态代理一样
KgcInstall pr = new KgcInstall();
CglibProxy cp = new CglibProxy(pr);
// 将真实对象传入动态代理 ,并生成相应的代理对象
KgcInstall proxyPr = (KgcInstall)cp.getProxy();
proxyPr.run();
》 AOP 的引入
现状(AOP 的演变过程):
- 有一个支付接口,有很多具体的实现类
- 现在我想统计每一种支付方式都需要花费多久
解决方案 :
1、每一个类的方法里都加入两个部分:
-
- 加入开始时间统计
- 加入结束时间统计
- 结束时间减去开始时间
2、提取工具类
将1.2 和 1.3 进行合并
public static void actionTime(long beginTime){
long endTime = System.currentTimeMillis();
System.out.println("执行使用了="+(endTime-beginTime));
}
3、问题: 如果有1000 个类需要修改
3.1 修改的太多,工作量太大
3.2 还原的时候很容易出现遗忘
解决方案 :
引入动态代理
引入CGLIB
思想: 不关心具体的事物,关注的是任意对象里的某一个点
4、问题 : 无论是动态代理还是CGLIB,对象里的方法都是一个完整的整体,不可分割
引入 AOP
AOP
概念: 是一种 编程范式(思想),用来帮助我们完善面向对象编程
面向 切面编程·
主要功能
日志记录,性能统计,安全控制,事务处理,异常处理等等。
主要意图
将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分 离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。