一、引入
Spring作为业界的经典框架,无论是在架构设计方面,还是在代码编写方面,都堪称行内典范。Spring框架中使用到了大量的设计模式,下面介绍比较有代表性的几种。
二、Spring常用的八种设计模式
2.1 工厂模式
-
工厂模式通常由应用程序直接使用new创建新的对象,为了将对象的创建和使用相分离,采用工厂模式,即应用程序将对象的创建及初始化职责交给工厂对象。
-
Spring使用工厂模式可以通过 BeanFactory(延迟注入) 或 ApplicationContext(容器启动时创建所有 bean,BeanFactory的扩展) 创建 bean 对象。例如:
-
applicationcontext.xml 配置文件
<bean id="student" class="com.happy.MyStudent"> <property name="age" value="18"/> </bean>
-
测试类
public class SpringDesignModeDemo { public static void main(String[] args) { ApplicationContext context = new FileSystemXmlApplicationContext("../applicationcontext.xml"); MyStudent myStudent = (MyStudent) context.getBean("student"); myStudent.getAge(); }
2.2 单例模式
-
Spring 中 bean 的默认作用域就是 singleton(单例)的,还有prototype 、request 、session 、global-session这几种作用域。
-
Spring 实现单例的方式:
- XML
<bean id="student" class="com.happy.MyStudent" scope="singleton"/>
- 注解
@Scope(value = "singleton")
- XML
-
Spring 通过 ConcurrentHashMap 实现单例注册表的特殊方式实现单例模式。Spring 实现单例的核心代码如下:
// 通过 ConcurrentHashMap(线程安全) 实现单例注册表
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
// 检查缓存中是否存在实例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//...省略了很多代码
try {
singletonObject = singletonFactory.getObject();
}
//...省略多行代码
// 如果实例对象在不存在,注册到单例注册表中。
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
//将对象添加到单例注册表
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
}
}
}
2.3 适配器模式
- Spring AOP 的实现是基于代理模式,但是 Spring AOP 的增强或通知(Advice)使用到了适配器模式,与之相关的接口是AdvisorAdapter 。
- Advice 常用的类型有:BeforeAdvice、AfterAdvice、AfterReturningAdvice等。每个类型Advice(通知)都有对应的拦截器:MethodBeforeAdviceInterceptor、AfterReturningAdviceAdapter、AfterReturningAdviceInterceptor。Spring预定义的通知要通过对应的适配器,适配成 MethodInterceptor接口(方法拦截器)类型的对象。
- 在Spring MVC中,DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由HandlerAdapter 适配器处理。HandlerAdapter 作为期望接口,具体的适配器实现类用于对目标类进行适配,Controller 作为需要适配的类。
2.4 装饰模式
- Spring的applicationContext中配置的dataSource,可能是不同类型的数据库,也可能是不同的数据源。sessionFactory根据客户的每次请求,将dataSource属性设置成不同的数据源,以到达切换数据源的目的。
- Spring中用到的包装器模式在类名上有两种表现:一种是类名中含有Wrapper,另一种是类名中含有Decorator。基本上都是动态地给一个对象添加一些额外的职责。
2.5 代理模式
- Spring的Proxy模式在aop中有体现,比如JdkDynamicAopProxy和Cglib2AopProxy。
- Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,Spring AOP会使用Cglib,它会生成一个被代理对象的子类来作为代理。
- AOP也可以使用 AspectJ实现,Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。
2.6 观察者模式
- Spring中Observer模式常用的地方是listener的实现。如ApplicationListener。
- Spring 事件驱动模型是观察者模式的一个经典应用,它在很多场景都可以解耦代码。
2.7 策略模式
- Spring中在实例化对象的时候用到Strategy模式,还有加载资源文件的方式,使用了不同的方法,比如:ClassPathResourece、FileSystemResource、ServletContextResource、UrlResource 都有共同的借口Resource。
- 在Aop的实现中,采用了两种不同的方式,JDK动态代理和CGLIB代理;
- Spring的事务管理,PlatformTransactionManager代表事务管理接口,但是它不知道底层如何管理事务,它只要求事务管理提供开始事务(getTransaction(),commit(),rollback()三个方法,但是如何实现则交给具体实现类来完成–不同的实现类代表不同的事务管理策略。
2.8 模板方法模式
- 模板方法模式是一种行为设计模式,它定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤的实现方式。
- Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。一般情况下,我们都是使用继承的方式来实现模板模式,但是 Spring 并没有使用这种方式,而是使用Callback 模式与模板方法模式配合,既达到了代码复用的效果,同时增加了灵活性。
三、总结
- 工厂模式 : Spring使用工厂模式通过 BeanFactory、ApplicationContext 创建 bean 对象。
- 单例模式 : Spring 中的 Bean 默认都是单例的。
- 适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式。
- 装饰者模式: 需要连接不同的数据库、不同的数据源。
- 代理模式 : Spring AOP 功能的实现。
- 观察者模式: Spring 事件驱动模型是观察者模式的一个经典应用。
- 策略模式:Spring加载资源的方式。
- 模板方法模式 : Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类。