Spring之代理设计模式原理与代码展示
来源:互联网 发布:企业专利数据库 编辑:程序博客网 时间:2024/05/24 05:53
1.代理设计模式
1.代理设计模式
代理设计模式的原理:使用一个代理将对象包装起来,然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。
- GoF95 一共定义了23种设计模式.代理设计模式是非常重要模式之一.
- 作用:
- 对目标对象访问进行控制.在访问目标前,后进行功能的扩展.
- 可以进行功能扩展的技术:
- 过滤器
- 拦截器
- 代理
- …
2- 代理方式:
- 静态代理:只能代理一种类型的对象.代理类需要自定义开发.
- 动态代理:可以代理所有的类型对象.代理类由代理工具类动态生成.
-JDK动态代理
- 基于接口进行代理.
- 目标对象必须实现相关的接口,才能使用这种代理方式.
- 代理类和目标类实现了共同的接口.
- InvocationHandler
- Cglib/Javassist
- 基于继承方式进行代理的.
- 代理类是目标类的子类.
3- 代理流程:
- 使用代理前代码结构:
- A(客户端) -> D(目标程序(业务代码+非业务代码(日志,事务,权限,校验…)))
- 使用代理后代码结构:
- A(客户端) ->B(代理对象) ->C(调用处理器(非业务代码(日志,事务,权限,校验…))-> D(目标程序(业务代码))
4- 代理可以解决系统中哪些问题?
- 日志打印,事务处理,权限控制,数据校验…
2.代理设计模式的使用案例
1.定义目标类接口
public interface MathCalculator {
int add(int i,int j);
int sub(int i,int j);
int mul(int i, int j);
int div(int i,int j);
}
2.定义目标类
//如何增加日志扩展
//如果在已有的业务代码中增加日志扩展代码,不好:
//业务代码和非业务代码进行耦合.不利于维护.日志代码 属于重复性代码.
//目标类
public class EazyImpl implements MathCalculator{
@Override
public int add(int i, int j) {
int result = i + j;
System.out.println("方法内部打印:result="+result);
return result;
}
@Override
public int sub(int i, int j) {
int result = i - j;
System.out.println("方法内部打印:result="+result);
return result;
}
@Override
public int mul(int i, int j) {
int result = i * j;
System.out.println("方法内部打印:result="+result);
return result;
}
@Override
public int div(int i, int j) {
int result = i / j;
System.out.println("方法内部打印:result="+result);
return result;
}
}
3.定义工具类
//工具类:用于动态生成代理对象.
public class ProxyProvider {
private Object targetObject ;
public ProxyProvider(Object targetObject){
this.targetObject = targetObject ;
}
//动态创建代理对象.
public Object getProxy(){
/**
* ClassLoader loader : 类加载器
* 用于加载代理类到JVM中运行.一般传递目标对象的类加载器就可以了.
* Class<?>[] interfaces : 接口类型数组
* JDK动态代理,基于接口的. 目标类和代理类实现共同的接口.需要通过目标对象来获取接口类型
* InvocationHandler h : 调用处理器
*代理类是在内存中动态生成的.无法将扩展代码写在代理类中.所以,需要通过InvocationHandler接口编写实现类,来完成功能扩展.
*/
returnProxy.newProxyInstance(
targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
newInvocationHandler(){
/**
* Object proxy : 代理对象
* Method method : 调用目标方法对象
* Object[] args : 调用目标方法的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
Object result = null ;
try {//扩展日志
System.out.println("[★日志]["+method.getName()+"方法开始][参数值:
"+(args==null?"":Arrays.asList(args))+"]");
//执行目标
result = method.invoke(targetObject, args);
//扩展日志
System.out.println("[★日志]["+method.getName()+"方法结束][返回值:"+result+"]");
} catch (Exception e) {
//扩展日志
e.printStackTrace();
Throwable cause = e.getCause();
if(cause!=null){
System.out.println("[★日志]["+method.getName()+"方法异常了][异常消息:"+cause.getMessage()+"]");
}
} finally{
//扩展日志
System.out.println("[★日志]["+method.getName()+"方法最终结束了]");
}
return result;
}
});
}
}
4.定义测试类
public static void main(String[] args) {
MathCalculator calculator = new EazyImpl(); //目标对象
calculator.add(10, 5);
calculator.sub(10, 5);
calculator.mul(10, 5);
calculator.div(10, 5);
System.out.println("------------------------------");
//通过工具类来创建代理对象
//代理对象的类名:$Proxy + 数字
Object proxyObject = new ProxyProvider(calculator).getProxy();
//A(客户端) -> B(代理程序) -> C(InvocationHandler(日志打印)) -> D(目标程序)
MathCalculator proxy = (MathCalculator)proxyObject;
proxy.add(10, 5);
proxy.sub(10, 5);
proxy.mul(10, 5);
proxy.div(10, 0);
}
阅读全文
0 0
- Spring之代理设计模式原理与代码展示
- 设计模式之策略模式代码展示
- 设计模式之代理模式代码
- Spring原理之代理与动态代理模式总结(四)
- 动态代理设计模式[Spring AOP原理(核心模式)]
- java与设计模式之代理模式
- 懒羊学习《深入浅出设计模式》C#代码手札之状态模式与代理模式
- 代理设计模式之静态代理与动态代理
- 代理设计模式之静态代理与动态代理
- 设计模式——代理模式实现与原理分析
- Java设计模式之代理模式实现及原理
- 设计模式之---代理模式(AOP的原理)
- 设计模式之代理模式 Android代码分析
- 代理模式与Spring
- java设计模式之静态代理与动态代理
- 设计模式之--装饰模式与代理模式的区别
- JavaScript代理设计模式原理
- 设计模式之代理
- 51nod 1102 -面积最大的矩形问题
- Spring Cloud和Docker构建微服务
- Linux 下系统调用 API 系统命令 内核函数 区别
- canvas 简单的绘制H5页面生成图片
- linux下redis安装配置及redis常用命令
- Spring之代理设计模式原理与代码展示
- [寒假计划]
- laravel schedule小记
- 武汉工程科技学院.网络集成与安全.综合实习报告.2017.12.5
- C++命名规则
- 给定一个包含从0,1,2,...,n中取出的n个不同数字的数组,找到数组中缺少的数字。
- SQL求解两个时间差
- Spark性能调优:checkPoint的使用
- mongo-java-driver -3.2.2学习笔记-05-身份认证