设计模式之jdk动态代理模式、责任链模式-java实现
设计模式之JDK动态代理模式、责任链模式
需求场景
- 当我们的代码中的类随着业务量的增大而不断增大仿佛没有尽头时,我们可以考虑使用动态代理设计模式,代理类的代码量被固定下来,不会随着业务量的增大而增大。
- 当我们想要在类方法调用前、调用后等自动插入一些额外的功能时,可以考虑使用动态代理来实现而不用修改类的源代码。
- 动态代理对象是动态生成的,不是定义好的,所以动态代理模式可以作为一种解除耦合的手段。
- 动态代理模式也可以作为责任链设计模式的实现手段。
前提条件
JDK动态代理的被代理对象是需要实现接口的。
成熟案例
Spring框架的AOP编程,就是使用动态代理实现的。
手写案例
首先,我们的被代理对象要实现一个公共的接口,这样可以做到一个大类型的整体代理,下面是这个接口及其实现类。
public interface IMyClass{
public void saySomething(String msg);
}
public class MyClassImpl implements IMyClass{
@Override
public void saySomething(String msg){
System.out.println(msg);
}
}
现在我们想要使用代理对象来代理这个类,但是代理对象从哪里来呢?所以,我们需要写一个动态产生代理对象的“工厂”。这个“工厂”需要实现一个叫做 InvocationHandler 的接口。
public class MyProxy<T> implements InvocationHandler {
//实际对象,即被代理对象
private T target;
//绑定方法,获取代理对象
public T bind(T target) {
this.target = target;
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用方法前做的事");
//调用方法
Object result = method.invoke(target, args);
System.out.println("调用方法后做的事");
return result;
}
}
现在我们有了被代理对象,有了代理对象的生产“工厂”,就可以开始试一试了。
public class Test{
public static void main(String[] args){
//获取代理对象
IMyClass myClassProxy = new MyProxy<IMyClass>().bind(new MyClassImpl());
myClassProxy.saySomething("Hello World!");
}
}
结果如下:
调用方法前做的事
Hello World!
调用方法后做的事
模拟拦截器
使用jdk代理模式很容易实现一个拦截器,下面是我们的拦截器的接口和一个实现类。
public interface Interceptor{
public boolean before(Object proxy, Method method, Object[] args, Object target) throws Exception;
public Object around(Object proxy, Method method, Object[] args, Object target) throws Exception;
public void after(Object proxy, Method method, Object[] args, Object target) throws Exception;
}
public class InterceptorImpl implements Interceptor{
@Override
public boolean before(Object proxy, Method method, Object[] args, Object target) throws Exception{
System.out.println("Before!");
if(((String)args[0]).length() <= 10){
//未通过验证
System.out.println("It's too short!");
return false;
}
//通过验证
return true;
}
@Override
public Object around(Object proxy, Method method, Object[] args, Object target) throws Exception{
System.out.println("add something satrt!");
args[0] += " world!";
Object result = method.invoke(target, args);
System.out.println("add something end!");
return result;
}
@Override
public void after(Object proxy, Method method, Object[] args, Object target) throws Exception{
System.out.println("After!");
}
}
将我们的代理类生产“工厂”稍作修改
public class MyProxy<T> implements InvocationHandler {
//实际对象,即被代理对象
private T target;
//我们的拦截器类名
private String interceptorName;
//绑定方法,获取代理对象
public T bind(T target, String interceptorName) {
this.target = target;
this.interceptorName = interceptorName;
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(null == this.interceptorName){
return method.invoke(target, args);
}
Object result = null;
Interceptor interceptor = (Interceptor)Class.forName(this.interceptorName).newInstance();
if(interceptor.before(proxy, method, args, target)){
result = method.invoke(target, args);
}else{
result = interceptor.around(proxy, method, args, target);
}
interceptor.after(proxy, method, args, target);
return result;
}
}
试一试我们的拦截器
public class Test {
public static void main(String[] args) {
IMyClass myClassProxy = new MyProxy<IMyClass>().bind(new MyClassImpl(), "com.test.InterceptorImpl");
myClassProxy.saySomething("hello");
System.out.println("***************************************");
myClassProxy.saySomething("123456789012");
}
}
结果如下:
Before!
It's too short!
add something satrt!
hello world!
add something end!
After!
Before!
123456789012
After!
可以看到,我们成功实现了拦截的功能,增强了方法。
进阶责任链模式
责任链模式可以基于Jdk动态代理实现,模拟一下多个拦截器对同一个对象的拦截,你可以想象成一个员工要请假,把请假条先交给小组长签字,然后给项目经理签字,再返回给小组长,再到自己手上的场景。这个被代理的对象就是这个请假条,这些拦截器就是小组长和项目经理。
首先,我们再实现一个项目经理,把“小组长”的代码稍稍改一下即可。
public class InterceptorImpl1 implements Interceptor{
@Override
public boolean before(Object proxy, Method method, Object[] args, Object target) throws Exception{
System.out.println("Before1!");
if(((String)args[0]).length() <= 10){
//未通过验证
System.out.println("It's too short1!");
return false;
}
//通过验证
return true;
}
@Override
public Object around(Object proxy, Method method, Object[] args, Object target) throws Exception{
System.out.println("add something satrt1!");
args[0] += " world1!";
Object result = method.invoke(target, args);
System.out.println("add something end1!");
return result;
}
@Override
public void after(Object proxy, Method method, Object[] args, Object target) throws Exception{
System.out.println("After1!");
}
}
下面开始“递交请假条”。
public class Test {
public static void main(String[] args) {
IMyClass myClassProxy = new MyProxy<IMyClass>().bind(new MyClassImpl(), "com.test.InterceptorImpl");
IMyClass myClassProxy1 = new MyProxy<IMyClass>().bind(myClassProxy, "com.test.InterceptorImpl1");
myClassProxy1.saySomething("hello");
System.out.println("***************************************");
myClassProxy1.saySomething("123456789012");
}
}
结果如下
Before1!
It's too short1!
add something satrt1!
Before!
hello world1!
After!
add something end1!
After1!
Before1!
Before!
123456789012
After!
After1!
看,是不是外面又套了一层?这个想不想是Spring的AOP编程的效果呢?其实原理就是这样!
总结
动态代理模式是一种非常重要的设计模式。我们可以看到,很多的框架都大量使用动态代理模式来实现其特殊的功能,这个设计模式需要好好好掌握。
责任链设计模式可以看作是一种扩展,仔细体会一下就能够领会其中的奥妙。大家可以仔细看看责任链模式案例运行结果的顺序,有助于理解哦!
开发模式是前任对某一类相似问题的解决方案进行的总结,我们可以从中吸取经验,但也不能盲目使用,也不能为了使用设计模式而使用设计模式。作为一个coder,要始终保持自己活跃的思维,不能将思维局限在一个设计模式上。开发熟练度在一定程度上决定了你的工作效率,但是思维的活跃度和发散性决定了你的天花板,也在很大程度上决定了你的工作效率。
你虽然在为别人工作,但是,你也在创造自己的世界!
设计模式之jdk动态代理模式、责任链模式-java实现的更多相关文章
- Java 设计模式系列(二二)责任链模式
Java 设计模式系列(二二)责任链模式 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求 ...
- 设计模式之Jdk动态代理
什么是动态代理呢?就是在java的运行过程中,动态的生成的代理类.(为了更熟悉的了解动态代理,你必须先熟悉代理模式,可点击设计模式之代理模式 阅读)我们知道java属于解释型语言,是在运行过程中,寻找 ...
- 设计模式之(十四)责任链模式(Chain of Responsibility)
在业务场景中,有很多是需要审批的.审核方式还可能常常发生变化,而责任链模式就是为了解决这种场景的情况的. 责任链模式定义:十多个对象都有机会处理请求,从而避免发送者和接受者之间的耦合关系.讲这些对象连 ...
- 《Android源码设计模式》--状态模式--责任链模式--解释器模式--命令模式--观察者模式--备忘录模式--迭代器模式
[状态模式] No1: Wifi设置界面是一个叫做WifiSetting的Fragment实现的 No2: 在不同的状态下对于扫描Wifi这个请求的处理是完全不一样的.在初始状态下扫描请求被直接忽略, ...
- Java设计模式之JDK动态代理原理
动态代理核心源码实现public Object getProxy() { //jdk 动态代理的使用方式 return Proxy.newProxyInstance( this.getClass(). ...
- [19/04/29-星期一] GOF23_行为型模式(责任链模式、迭代器模式)
一.行为模式 二.责任链模式(chainOfResponsibility) [一个请求类] /*** 请假类 * 封装请假的基本信息 */ package cn.sxt.chainOfResponsi ...
- Java设计模式从精通到入门一 责任链模式
一直都想对设计模式有一个深刻的认识,这样对于阅读源码的时候就不会那么吃力了.于是有了想要记录下设计模式的笔记.打算从自己不怎么熟悉的设计模式开始写,里面穿插着一点自己的想法,希望自己写完后,会又一 ...
- 设计模式学习总结(十)责任链模式(Chain Of Responsibility)
责任链主要指通过一连串的操作来实现某项功能或者在处理相关的业务时,对于自己的业务则进行处理,反之,对于不属于自己的业务,则进行下发! 一.示例展示: 以下例子主要通过对煤矿对井下警告信息的处理来进 ...
- 《精通Python设计模式》学习行为型之责任链模式
感觉是全新的学习了. 因为在以前的工作中,并没有有意识的去运用哪一种编程模式. 以后要注意的了. 这才是高手之路呀~ class Event: def __init__(self, name): se ...
随机推荐
- udt通信java
udt协议是什么? 简单的是udp重发 经过上次的修正,重新测试,修复,测试各种环境,再次查找出源码错误,重新修正 修正内容在git中的修正说明中 同时针对之后的应用,对封装的代码也做了修改和重构 代 ...
- mongodb mac
==> mongodb To have launchd start mongodb now and restart at login: brew services start mongodb O ...
- 4种好用的python编辑器
1.Sublime Text: 这是一个轻量级的代码编辑器,跨平台,支持几十种编程语言,包括Python,Java,C/C++等,小巧灵活,运行轻快,支持代码高亮.自动补全.语法提示,插件扩展丰富,是 ...
- Intellij IDEA快捷键大全汇总(2019更新)
Intellij IDEA快捷键大全汇总(2019) Ctrl+Shift + Enter,语句完成“!”,否定完成,输入表达式时按 “!”键 Alt+回车 导入包,自动修正 Ctrl+N 查找类 ...
- 转载:消息队列MQ
本文大概围绕如下几点进行阐述: 为什么使用消息队列? 使用消息队列有什么缺点? 消息队列如何选型? 如何保证消息队列是高可用的? 如何保证消息不被重复消费? 如何保证消费的可靠性传输? 如何保证消息的 ...
- 基于HALCON的模板匹配方法总结
注:很抱歉,忘记从转载链接了,作者莫怪.... 基于HALCON的模板匹配方法总结 很早就想总结一下前段时间学习HALCON的心得,但由于其他的事情总是抽不出时间.去年有过一段时间的集中学习,做了许多 ...
- Xcode中编译iOS程序,运行出错:Thread 1: signal SIGABRT
添加一个全局Exception Breakpoint 就检测出来了 导航栏里面 Debug 菜单里面
- V-REP Remote API(C++)实现简单的关节转动
基础内容参考:https://www.cnblogs.com/eternalmoonbeam/p/10753149.html V-REP客户端设置: 在V-REP场景文件中需要添加三个实体,包括两个形 ...
- F查询和Q查询,事务及其他
F查询和Q查询 F查询 在上面所有的例子中,我们构造的过滤器都只是将字段值与某个我们自己设定的常量做比较.如果我们要对两个字段的值做比较,那该怎么做呢? Django 提供 F() 来做这样的比较.F ...
- css note
1.text-align规定了其子元素的对齐方式,当设置在子元素无效时,尝试设置在父元素,子元素可以水平居中: 2.vertical-align使用的前提,首先元素必须是display:inline ...