如果仅仅是想学会使用,则可以不学习设计模式,如果想深入层次的学习Spring底层源码,则设计模式是必不可少的!
下面从几个方面进行介绍
(1) Spring 源码中使用了哪些设计模式?
(2) 怎样学习设计模式?
(3) 推荐设计模式的书籍
Spring源码中使用了哪些设计模式?spring 中使用了多种设计模式,下面简单介绍一下主要的设计模式
(1) 单例模式
保证独一无二,为了提高资源重复利用,通过技术手段保证在整个系统运行阶段,只有一个实例
场景: 配置文件、监控程序、IOC 容器、日历
实现手段: 懒汉式、饿汉式、注册登记式、反序列处理
Spring最常用的,注册登记式,效率性能最高的
Spring中bean的默认作用域就是singleton(单例)。
实现方式:
xml : <bean id="userService" class="top.snailclimb.UserService" scope="singleton"/>注解:@Scope(value = "singleton")Spring 通过 ConcurrentHashMap 实现单例注册表的特殊方式实现单例模式。Spring 实现单例的核心代码如下
(2) 代理设计模式
代理模式在 AOP 中的应用
AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用Cglib ,这时候Spring AOP会使用 Cglib 生成一个被代理对象的子类来作为代理,如下图所示:
当然你也可以使用 AspectJ ,Spring AOP 已经集成了AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。
使用 AOP 之后我们可以把一些通用功能抽象出来,在需要用到的地方直接使用即可,这样大大简化了代码量。我们需要增加新功能时也方便,这样也提高了系统扩展性。日志功能、事务管理等等场景都用到了 AOP 。
Spring AOP 和 AspectJ AOP 有什么区别?
Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。
Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单,
如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比Spring AOP 快很多。
(3) 模板方法
应用场景: JdbcTemplate 工作流
代码场景: 模拟Spring JdbcTemplate的简单实现
Spring 中 jdbcTemplate、hibernateTemplate 等于 Template 结尾的对数据库操作的类,它们就使用到了模板模式。一般情况下,我们都是使用继承的方式来实现模板模式,但是 Spring 并没有使用这种方式,而是使用Callback 模式与模板方法模式配合,既达到了代码复用的效果,同时增加了灵活性。
(4) 观察者模式
观察者模式是一种对象行为型模式。它表示的是一种对象与对象之间具有依赖关系,当一个对象发生改变的时候,这个对象所依赖的对象也会做出反应。Spring 事件驱动模型就是观察者模式很经典的一个应用。Spring 事件驱动模型非常有用,在很多场景都可以解耦我们的代码。比如我们每次添加商品的时候都需要重新更新商品索引,这个时候就可以利用观察者模式来解决这个问题。
Spring 事件驱动模型中的三种角色
事件角色
ApplicationEvent (org.springframework.context包下)充当事件的角色,这是一个抽象类,它继承了java.util.EventObject并实现了 java.io.Serializable接口。
Spring 中默认存在以下事件,他们都是对 ApplicationContextEvent 的实现(继承自ApplicationContextEvent):
ContextStartedEvent:ApplicationContext 启动后触发的事件;ContextStoppedEvent:ApplicationContext 停止后触发的事件;ContextRefreshedEvent:ApplicationContext 初始化或刷新完成后触发的事件;ContextClosedEvent:ApplicationContext 关闭后触发的事件。事件监听者角色
ApplicationListener 充当了事件监听者角色,它是一个接口,里面只定义了一个 onApplicationEvent()方法来处理ApplicationEvent。ApplicationListener接口类源码如下,可以看出接口定义看出接口中的事件只要实现了 ApplicationEvent就可以了。所以,在 Spring中我们只要实现 ApplicationListener 接口实现 onApplicationEvent() 方法即可完成监听事件
事件发布者角色
ApplicationEventPublisher 充当了事件的发布者,它也是一个接口。ApplicationEventPublisher 接口的publishEvent()这个方法在AbstractApplicationContext类中被实现,阅读这个方法的实现,你会发现实际上事件真正是通过ApplicationEventMulticaster来广播出去的。具体内容过多,就不在这里分析了,后面可能会单独写一篇文章提到。
Spring 的事件流程总结
定义一个事件: 实现一个继承自 ApplicationEvent,并且写相应的构造函数;
定义一个事件监听者:实现 ApplicationListener 接口,重写 onApplicationEvent() 方法;
使用事件发布者发布消息: 可以通过 ApplicationEventPublisher 的 publishEvent() 方法发布消息。
Example:
(5) 适配器模式
适配器模式(Adapter Pattern) 将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。
spring AOP中的适配器模式
我们知道 Spring AOP 的实现是基于代理模式,但是 Spring AOP 的增强或通知(Advice)使用到了适配器模式,与之相关的接口是AdvisorAdapter 。Advice 常用的类型有:BeforeAdvice(目标方法调用前,前置通知)、AfterAdvice(目标方法调用后,后置通知)、AfterReturningAdvice(目标方法执行结束后,return之前)等等。每个类型Advice(通知)都有对应的拦截器:MethodBeforeAdviceInterceptor、AfterReturningAdviceAdapter、AfterReturningAdviceInterceptor。Spring预定义的通知要通过对应的适配器,适配成 MethodInterceptor接口(方法拦截器)类型的对象(如:MethodBeforeAdviceInterceptor 负责适配 MethodBeforeAdvice)。
代码场景:登录,为了兼容旧系统的登录功能,在老系统的基础之上进行兼容编程,Spring Adapter结尾的
(6) 装饰器模式
装饰者模式可以动态地给对象添加一些额外的属性或行为。相比于使用继承,装饰者模式更加灵活。简单点儿说就是当我们需要修改原有的功能,但我们又不愿直接去修改原有的代码时,设计一个Decorator套在原有代码外面。其实在 JDK 中就有很多地方用到了装饰者模式,比如 InputStream家族,InputStream 类下有 FileInputStream (读取文件)、BufferedInputStream (增加缓存,使读取文件速度大大提升)等子类都在不修改InputStream 代码的情况下扩展了它的功能
应用场景: IO流 、数据源、也用代码改造一个旧系统,在Spring 中Decorator结尾的,Wrapper结尾的都是。
(7) 委派模式
代理模式的特殊情况,全权代理
应用场景: 项目经理、Dispatcher
代码场景: Spring 中ServletDispatcher /Delegate 命名结尾的都是委派模式
怎样学习设计模式(1) 调整好心态,不要指望一蹴而就,不可浮躁。
学习和掌握设计模式需要一个过程,不同的阶段看这些设计模式有不同的领悟和感受。不要指望真正的设计模式的书籍既简单又有趣,一看就懂的。
(2) 学习设计模式的第一步 : 准确理解每个设计模式的功能、基本结构、标准实现,了解适合使用它的场景以及使用的效果。
(3) 学习设计模式的第二步: 实际的开发中,尝试着使用这些设计模式,并反复思考和总结是否使用得当,是否需要做一些变化。
(4) 学习设计模式的第三步 : 再回头去看设计模式的理论,有了实际的模式应用经验再看设计模式,会有不同的感悟,一边看一边结合着应用经验来思考。比如设计模式的本质功能是什么?它是如何实现的?z这种实现方式还可以在什么地方应用? 如何才能把这个设计模式和具体的应用结合起来?这个设计模式的出发点是什么?等等。可以有很多考虑的点,从不同的角度对设计模式进行思考。
(5) 第四步 : 多次反复学习设计模式的第二步和第三步。也就是在实际开发中使用,然后结合理论思考,然后再应用,再思考...如此循环,反复多次,直到达到对设计模式基本掌握的水平。
简而言之,要注意使用设计模式的理论和实践相结合,理论指导实践,实践反过来加深对理论的理解,如此反复循环,成螺旋式上升!
设计模式书籍的推荐这本书非常经典,大家可以反复阅读,由于网上已没有纸质书,只有电子版,
有需要电子版的,可以私信。