文章目录
1.概念
代理模式是二十三种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来——解耦。调用目标方法时先调用代理对象的方法,减少对目标方法的调用和打扰,同时让附加功能能够集中在一起也有利于统一维护。

使用代理之后:

生活中的代理
- 广告商找大明星拍广告需要经过经纪人
- 合作伙伴找大老板谈合作要约见面时间需要经过秘书
- 房产中介是买卖双方的代理
相关术语
- 代理:将非核心逻辑剥离出来以后,封装这些非核心逻辑的类、对象、方法。
- 目标:被代理“套用”了非核心逻辑代码的类、对象、方法。
2.静态代理机制
2.1 静态代理业务调用

2.2 静态代理实现
package com.atguigu;
public class CalculatorProxy implements Calculator{
private Calculator target;
public CalculatorProxy(Calculator target) {
this.target = target;
}
@Override
public int add(int i, int j) {
System.out.println("[日志] add方式开始执行: 参数1:"+i+"~~"+ "参数2:"+j);
int result = target.add(i,j);
System.out.println("[日志] add方式结束执行: 结果是"+result);
return result;
}
@Override
public int sub(int i, int j) {
System.out.println("[日志] sub方式开始执行: 参数1:"+i+"~~"+ "参数2:"+j);
int result = target.sub(i,j);
System.out.println("[日志] sub方式结束执行: 结果是"+result);
return result;
}
@Override
public int mul(int i, int j) {
System.out.println("[日志] mul方式开始执行: 参数1:"+i+"~~"+ "参数2:"+j);
int result = target.mul(i,j);
System.out.println("[日志] mul方式结束执行: 结果是"+result);
return result;
}
@Override
public int div(int i, int j) {
System.out.println("[日志] div方式开始执行: 参数1:"+1+"~~"+ "参数2:"+j);
int result = target.div(i,j);
System.out.println("[日志] div方式结束执行: 结果是"+result);
return result;
}
}
2.3 测试静态代理代码
@Test
public void testUser() throws SQLException {
CalculatorImpl target = new CalculatorImpl();
Calculator calculator = new CalculatorProxy(target);
int add = calculator.add(100, 100);
int div = calculator.div(100, 10);
System.out.println("求和结果:"+add);
System.out.println("商的结果:"+div);
}
3.动态代理机制
3.1 动态代理介绍

3.2 创建代理对象
package com.atguigu;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxy {
public static Object getProxy(Object target){
/**
* 参数介绍
* 1.类加载器
* 2.目标对象的接口
* 3.业务执行回调函数InvocationHandler handler对象
*/
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
try {
System.out.println("[日志]"+method.getName()+"方式开始执行: 参数1:"+args[0]+"~~"+ "参数2:"+args[1]);
result = method.invoke(target,args);
System.out.println("[日志]"+method.getName()+"方式开始结束: 返回值:"+result);
}catch (Exception e){
System.out.println("[日志]"+method.getName()+"|异常信息:"+e.getMessage());
}finally {
System.out.println("[日志]动态代理执行完成: 返回值结果:"+result);
}
return result;
}
});
}
}
3.3 测试结果显示

4.Cglib动态代理
4.1 编辑代理类
public class CglibProxy {
public static Object getProxy(Object target){
//1.定义增强器对象
Enhancer enhancer = new Enhancer();
//2.为属性赋值
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object result = null;
try {
System.out.println("[日志]"+method.getName()+"方式开始执行: 参数1:"+objects[0]+"~~"+ "参数2:"+objects[1]);
result = method.invoke(target,objects);
System.out.println("[日志]"+method.getName()+"方式开始结束: 返回值:"+result);
}catch (Exception e){
System.out.println("[日志]"+method.getName()+"|异常信息:"+e.getMessage());
}finally {
System.out.println("[日志]动态代理执行完成: 返回值结果:"+result);
}
return result;
}
});
return enhancer.create();
}
}
4.2 编辑测试类
@Test
public void testCglibProxy(){
CalculatorImpl target = new CalculatorImpl();
Calculator calculator = (Calculator) CglibProxy.getProxy(target);
System.out.println(calculator.getClass());
int add = calculator.add(100, 200);
System.out.println("返回值结果:"+add);
}
5.总结
-
代理方式不同
- JDK代理使用的是反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
- CGLIB代理使用字节码处理框架asm,对代理对象类的class文件加载进来,通过修改字节码生成子类。
-
效率不同
- JDK创建代理对象效率较高,执行效率较低;
- CGLIB创建代理对象效率较低,执行效率高。
-
生成方式不同
- JDK动态代理机制是委托机制,只能对实现接口的类生成代理,通过反射动态实现接口类;
- CGLIB则使用的继承机制,针对类实现代理,被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,因为是继承机制,不能代理final修饰的类。
-
是否需要第三方类库
-
JDK代理是不需要依赖第三方的库,只要JDK环境就可以进行代理,需要满足以下要求:
- 实现InvocationHandler接口,重写invoke()
- 使用Proxy.newProxyInstance()产生代理对象
- 被代理的对象必须要实现接口
-
CGLib 必须依赖于CGLib的类库,需要满足以下要求:
- 实现MethodInterceptor接口,重写intercept()
- 使用Enhancer对象.create()产生代理对象
-
4284




被折叠的 条评论
为什么被折叠?



