工厂模式
由工厂类根据传入的参数,动态决定应该创建哪一个产品类的对象,实现“创建与使用相分离”。
简单工厂模式
只有一个工厂类,使用静态方法来创建产品对象。
- 单一工厂类负责所有产品的创建,职责过重,违背高聚合原则;
- 增加新产品必须修改工厂方法逻辑,违背开闭原则
Spring读取xml配置文件,将<bean>
元素转化成BeanDefinition
对象,通过BeanDefinitionRegistry
将这些bean注入到BeanFactory
中,保存在其ConcurrentHashMap里。
这里的BeanFactory
就是一个简单工厂,特点是延迟注入(使用到某个bean时才会创建)。
而ApplicationContext
就是容器启动时创建所有bean,并扩展了除依赖注入外的其他功能。
工厂方法模式
在简单工厂基础上,抽象出一个工厂接口,各子工厂类实现创建产品对象的抽象方法。
Spring的FactoryBean
就是一个定义了getObject
方法的工厂接口。
通过getBean
获取实现了FactoryBean
接口的bean时,会自动调用其getObject
方法,所以返回的不是该类的实例,而是其getObject
方法的返回值。
典型例子就是Spring和MyBatis的结合:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
这个class因为实现了FactoryBean
接口,注入的bean就是SqlSessionFactoryBean.getObject()
单例模式
系统中有些对象只需要一个即可,如线程池、缓存、日志对象、设备驱动等。
优点:
1.对于频繁使用的对象,节省重复创建的时间开销
2.由于new操作减少,系统内存的使用频率降低,减轻GC压力
Spring中bean的默认作用域就是singleton(单例),prototype则是每次创建新实例。
Spring通过维护ConcurrentHashMap
单例注册表的方式实现单例模式。
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
}
代理模式
给目标对象提供一个代理,以控制对该对象的访问。
优点:
1.代理作为一个中介,可保护目标对象
2.代理可以扩展目标对象的功能
静态代理:代理目标固定,在程序执行前就代理类的.class就存在了
动态代理:通过反射机制在程序运行期动态地为目标创建代理对象
Spring AOP就是基于动态代理,将那些与业务无关但又被业务模块调用的共同逻辑(如事物处理、日志管理、权限控制等)封装起来,提高代码复用率。
对于实现了接口的类,Spring AOP通过JDK Proxy创建代理对象;
对于没有实现接口的类,Spring AOP使用CgLib生产一个目标对象的子类作为代理。
Spring AOP 属于运行时增强,而 AspectJ 是编译时增强;Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。若切面较多,选择后者速度优势明显。
模版方法模式
定义一个操作的骨架,并将部分步骤延迟到子类中实现,从而达成不改变结构即可重定义特点步骤的效果。
public abstract class Template {
//模板方法
public final void TemplateMethod(){
PrimitiveOperation1();
PrimitiveOperation2();
PrimitiveOperation3();
}
protected void PrimitiveOperation1(){
// 当前类实现
}
// 由子类实现的方法
protected abstract void PrimitiveOperation2();
protected abstract void PrimitiveOperation3();
}
Spring的jdbcTemplate
就使用了模版方法模式,但不是通过继承来实现的,而是Callback 模式与模板方法模式配合,既达到了代码复用的效果,同时增加了灵活性。
观察者模式
适用场景:对象之间具有依赖关系,当一个对象改变,其依赖的对象也会做出反应。
Spring事件驱动模型就是观察者模式的一个经典应用。
事件:ApplicationEvent
,是一个抽象类,继承了java.util.EventObject
并实现了 java.io.Serializable
接口。
事件监听者:ApplicationListener
,是一个接口,只定义了onApplicationEvent
方法来处理ApplicationEvent
。
事件发布者:ApplicationEventPublisher
,是一个接口,定义了publishEvent
方法,在AbstractApplicationContext
中实现,通过ApplicationEventMulticaster
将事件广播出去。
适配器模式
将一个接口转化为另一个期望的接口,使接口不兼容的类可以一起工作。
目标接口:业务系统期望的接口;
适配者:被适配的组件类;
适配器:通过引用或继承适配者对象,使客户可按目标接口的格式访问适配者。
Spring MVC的请求处理器有多种实现方式(继承Controller的、基于注解方式的、HttpRequestHandler),普通情况下想要调用需要if else判断instance of,再编写调用逻辑。一旦添加新的处理器,就需要修改代码,不符合开闭原则。
于是Spring定义了一个处理器适配器接口:
public interface HandlerAdapter {
// 用于判断当前HandlerAdapter是否能够处理当前请求
boolean supports(Object handler);
// 如果当前HandlerAdapter能够用于适配当前请求,那么就会处理当前请求中
// 诸如参数和返回值等信息,以便能够直接委托给具体的Handler处理
ModelAndView handle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception;
// 获取当前请求的最后更改时间,主要用于供给浏览器判断当前请求是否修改过,
// 从而判断是否可以直接使用之前缓存的结果
long getLastModified(HttpServletRequest request, Object handler);
}
DispatcherServlet
根据请求信息调用HandlerMapping
,解析请求对应的Handler
。根据Handler
获取其对应的HandlerAdapter
适配器子类(遍历所有适配器的supports方法),最后调用这个适配器子类的handle方法处理请求返回ModelAndView
。
这样,当需要新增处理器类时,只需手动实现一个对应的适配器子类即可,无需变动已有代码。
装饰器模式
动态地给对象附加一些额外的属性或行为,相比继承更灵活。
Spring中名称带Wrapper或Decorator的类。