Spring是一个非常优秀的开源框架,项目源码中所使用的设计模式随处可见,这篇文章主要记录一下Spring中常见的设计模式:
(1)工厂模式:Spring使用工厂模式,通过BeanFactory和ApplicationContext来创建对象
(2)单例模式:Bean默认为单例模式
(3)策略模式:例如Resource的实现类,针对不同的资源文件,实现了不同方式的资源获取策略
(4)代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术
(5)模板方法:可以将相同部分的代码放在父类中,而将不同的代码放入不同的子类中,用来解决代码重复的问题。比如RestTemplate, JmsTemplate, JpaTemplate
(6)适配器模式:Spring AOP的增强或通知(Advice)使用到了适配器模式,Spring MVC中也是用到了适配器模式适配Controller
(7)观察者模式:Spring事件驱动模型就是观察者模式的一个经典应用。
(8)桥接模式:可以根据客户的需求能够动态切换不同的数据源。比如我们的项目需要连接多个数据库,客户在每次访问中根据需要会去访问不同的数据库
一、工厂模式:
对于工厂模式不了解地读者可以阅读另外一篇文章:Java设计模式之创建型模式:工厂模式(简单工厂模式+工厂方法模式)
工厂模式是把创建对象的任务交给工厂,从而来降低类与类之间的耦合。Spring最主要的两个特性就是AOP和IOC,其中IOC就是控制反转,将对象的控制权转移给Spring,并由Spring创建实例和管理各个实例之间的依赖关系,其中,对象的创建就是通过BeanFactory 和 ApplicationContext 完成的。
1、首先看BeanFatory的源码:
public interface BeanFactory {
Object getBean(String name) throws BeansException;
<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
//省略...
}
BeanFactory是Spring里面最底层的接口,是IoC的核心,定义了IoC的基本功能,包含了各种Bean的定义、加载、实例化,依赖注入和生命周期管理。BeanFactroy采用的是延迟加载形式来注入Bean的,只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能提前发现一些存在的Spring的配置问题。
2、ApplicationContext接口作为BeanFactory的子类,除了提供BeanFactory所具有的功能外,还扩展了其他更完整功能,对于Bean创建,ApplicationContext在容器启动时,一次性创建了所有的Bean。
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
@Nullable
String getId();
String getApplicationName();
String getDisplayName();
long getStartupDate();
@Nullable
ApplicationContext getParent();
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
3、BeanFactory 和 ApplicationContext 在哪里初始化Bean就不展开细讲,主要看AbstractApplicationContext类的refresh()方法。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//省略...
try {
//省略...
//初始化所有的单实例 Bean(没有配置赖加载的)
finishBeanFactoryInitialization(beanFactory);
}catch (BeansException ex) {
//省略...
}finally {
//省略...
}
}
}
二、单例模式:
对于单例模式不了解地读者可以阅读另外一篇文章:Java设计模式之创建型模式:单例模式
在Spring中的Bean默认的作用域就是singleton单例的。单例模式的好处在于对一些重量级的对象,省略了重复创建对象花费的时间,减少了系统的开销,第二点是使用单例可以减少new操作的次数,减少了GC线程回收内存的压力。
对于单例bean的创建方式,主要看DefaultSingletonBeanRegistry 的 getSingleton() 方法:
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/** 保存单例Objects的缓存集合ConcurrentHashMap,key:beanName --> value:bean实例 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
//检查缓存中是否有实例,如果缓存中有实例,直接返回
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//省略...
try {
//通过singletonFactory获取单例
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
//省略...
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
//返回实例
return singletonObject;
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
从源码中可以看出,是通过ConcurrentHashMap的方式,如果在Map中存在则直接返回,如果不存在则创建,并且put进Map集合中,并且整段逻辑是使用同步代码块包住的,所以是线程安全的。
三、策略模式:
对于策略模式不了解地读者可以阅读另外一篇文章:Java设计模式之行为型模式:策略模式
策略模式,简单来说就是封装好一组策略算法,外部客户端根据不同的条件选择不同的策略算法解决问题。比如在Spring的Resource类,针对不同的资源,Spring定义了不同的Resource类的实现类,以此实现不同的访问方式。我们看一张类图: