spring用到的设计模式

1.简单工厂

BeanFactory。首先看看它的API。
在这里插入图片描述
不难看出,它的作用是通过传入唯一的标识(可以是 bean名称,bean类型或者二者的组合)获得Bean对象,但具体是在传入参数前还是传入参数后创建要取决于实际情况。

实现过程

bean容器的启动阶段:

  1. 通过注解或者xml配置读取Bean配置,将Bean转换一个个的BeanDefinition对象;
  2. 通过BeanDefinitionRegistry将这些Bean注册到BeanFactory中,保存在内部的一个ConcurrentHashMap中;
  3. 调用Spring提供的扩展接口,允许通过实现 BeanFactoryPostProcessor.postProcessBeanFactory 在此处执行自定义的代码。比如PropertyPlaceholderConfigurer,解析 dataSource时用到的占位符,就是在这里执行的。

Bean容器的实例化阶段:
通过反射或者Cglib动态代理创建对象后,bean会走完以下周期:

  1. aware接口:如BeanFactoryAware,ApplicationContextAware,ResourceLoaderAware等;
  2. BeanPostProcessor.postProcessBeforeInitialization: Bean的后置处理器的Bean初始化之前的方法
  3. InitializingBean接口和 bean指定的 init-method 方法: Bean的初始化方法。
  4. BeanPostProcessor.postProcessAfterInitialization: Bean的后置处理器的Bean初始化之hou的方法
  5. DisposableBean接口: Bean的销毁方法 :destroy()。
设计意义

松耦合: 通过引入一个BeanFactory的工厂类,在依赖方和被依赖方的两个角色之间增加了一个第三方角色,由它来专门负责Bean的管理和解决依赖问题。
可扩展性强: Spring设计了很多个接口,可以在Bean的每个阶段通过实现接口的方式自定义很多处理,这样可以让Spring的可扩展性非常强。

2.工厂方法

FactoryBean。API如下:
在这里插入图片描述

实现原理

实现了FactoryBean的Bean,Spring通过 getBean() 获取该 bean 时,会调用 getObject() 方法,该方法返回的对象就是最终注册到 Spring 容器的对象,类型是 getObjectType() 获取到的类型。所以 getBean() 获取到的对象是 getObject() 返回的对象。

例子:
Mybatis 和 Spring的结合。
Mybatis首先配置一个扫描 Mapper 的类,该类扫描后将 Mapper 的class 类型修改为 MapperFactoryBean。 MapperFactoryBean 实现了 FactoryBean 接口,在这里返回的对象是通过 MapperProxyFactory 创建的 MapperProxy 代理对象,MapperProxy 才是真正执行的类。即被 Spring 扫描并创建的Mapper 对象,是通过 FactoryBean 创建的 MapperProxy 代理对象。

设计意义

一般情况下,Spring 是利用 class 属性通过反射创建Bean,但是如果创建的 Bean 过程和参数都比较复杂,如果通过反射的方法创建则需要大量的配置,使得代码难以维护,这时候如果能采用编程的方式是更好的选择。所以 Spring 提供了 FactoryBean 接口,用户只需要实现这个接口,则可以定制化的创建 Bean 对象,隐藏一些实例化 Bean 的细节。

3.单例模式

Spring 注入 Bean 实例在默认情况下就是单例的。
Spring 注入 Bean 都是发生在 AbstractBeanFactory.getBean()里,getBean() 里在真正创建 Bean 时首先会通过 getSingleton() 从容器里获取当前 Bean,如果获取到了,则不会往下走创建 Bean的逻辑,分析下 getSingleton():

	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// 检查一级缓存里是否有实例,如果有代表则说明已创建完毕
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			//如果为空,锁定一级缓存并进行处理
			synchronized (this.singletonObjects) {
				// 如果二级缓存有该实例,则说明还在创建中,不处理
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					// 这里是解决循环依赖的重要方法
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

4.适配器模式

Spring MVC 的适配器 HandlerAdatper。

实现原理(过程)

首先描述下Spring MVC的处理过程:

  1. 请求到达 DispatcherServlet.doService()。
  2. 调用处理器映射器HandlerMapping根据请求URL获取到Handler。
HandlerExecutionChain handler = mapping.getHandler(request);
  1. 根据找到的Handler寻找对应的处理器适配器HandlerAdapter。对应的Handler类别和Adapter的对照关系:
    在这里插入图片描述
	for (HandlerAdapter adapter : this.handlerAdapters) {
        if (adapter.supports(handler)) {
            return adapter;
        }
    }
  1. 处理器适配器 HandlerApapter 处理请求,返回 ModelAndView对象。
ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
  1. 视图解析器ViewResolver 解析 ModelAndView 返回具体的View
  2. DispatcherServlet 对 View 渲染视图。
设计意义

从上面的流程可以看到,HandlerAdapter 最主要的作用是调用 Handler 对用户的请求执行具体的业务代码。
HandlerApapter 的存在使Handler的扩展十分容易,如果想新增一个新的 Handler 类别,只需要新增一个新的 HandlerApapter 即可。
每个 Conroller 返回的结果类型可能都是不一样的,HandlerAdapter 可以帮助Spring 对这些结果的适配和转换。

5.装饰器模式

Spring的应用体现在两个地方:1. 类名带Wrapper 2. 类名带Decorator。

实现原理:即动态的给对象添加额外的职责

6.代理模式

典型应用就是 Aop 的动态代理。Aop也分两种代理模式:
JDK动态代理:主要涉及到两个类:Proxy 和 InvocationHandler。原理是通过 Proxy 利用 InvocationHandler 动态创建某一接口的实例,生成目标类的代理对象。JDK动态代理只适用于有实现接口的类。
CGLIB动态代理: 对指定的类生成一个子类,并重写其中的方法。主要原理是通过字节码底层继承要代理类实现。
对比:运行效率CGLIB高很多,创建对象上JDK高很多。

7.观察者模式

Spring 事件驱动模型就是用观察者模式实现的。

具体实现:

观察者模式主要分为三个角色:事件,事件发布者(事件源),事件订阅者(监听者)

事件: ApplicationEvent 抽象类,继承 java.util.EventObject,可通过 getSource() 获取事件源。在 Spring 中发布的事件对象都要继承该类。

public abstract class ApplicationEvent extends EventObject {

	private final long timestamp;

	public ApplicationEvent(Object source) {
		super(source);
		this.timestamp = System.currentTimeMillis();
	}

	public final long getTimestamp() {
		return this.timestamp;
	}

事件发布者(事件源): ApplicationEventPublisher 接口。其中最重要的继承接口是 ApplicationContext。 ApplicationContext 是spring 管理 bean 的全局容器。它负责加载 bean 配置,创建 bean 实例,维护 bean 的生命周期,也就是 IOC 容器。在特定的阶段便会发布事件 ApplicationEvent。

public interface ApplicationEventPublisher {
	default void publishEvent(ApplicationEvent event) {
		publishEvent((Object) event);
	}

	void publishEvent(Object event);
public abstract class AbstractApplicationContext implements ApplicationContext {
	protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
		getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);

		// Publish event via parent context as well...
		if (this.parent != null) {
			if (this.parent instanceof AbstractApplicationContext) {
				((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
			}
			else {
				this.parent.publishEvent(event);
			}
		}
	}
}

其中真正执行事件发布的是 ApplicationEventMulticaster(事件广播器)。他的作用是将事件发布给所有的事件监听器。

public interface ApplicationEventMulticaster {
	void multicastEvent(ApplicationEvent event);
}
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		Executor executor = getTaskExecutor();
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				invokeListener(listener, event);
			}
		}
	}

事件订阅者(监听者): ApplicationListener接口,继承自 java.util.EventListener。spring 容器里所有的事件监听器都要实现该接口。
ApplicationListener 只有一个方法 onApplicationEvent(E event)。实现该接口的类根据传入事件的具体类型进行处理。

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
	void onApplicationEvent(E event);
}

8.策略模式

Spring 的资源访问接口 Resource,Spring 本身大量使用了 Resource 接口访问底层资源。

Resoure api:

public interface Resource extends InputStreamSource {

	// 返回Resource访问的资源是否存在
	boolean exists();

	//返回资源文件是否代开
	default boolean isOpen() {
		return false;
	}

	URL getURL() throws IOException;
	
	URI getURI() throws IOException;
	
	// 返回资源文件的描述信息,通常是全限定文件名或者是URL
	String getDescription();

}

public interface InputStreamSource {
	
	//返回资源文件的输入流。每次调用都会创建一个新的输入流,调用者使用完必须关闭输入流。
	InputStream getInputStream() throws IOException;

}

Resource作为策略接口,本身并不提供对资源访问的实现逻辑,针对不同的资源访问方式,spring 会提供不同的实现类,由这些实现类负责不同的资源访问逻辑。

Spring 提供的 Resource 实现类:

  • UrlResource:访问网络资源的实现类。
  • ClassPathResource:访问类加载路径里资源的实现类。
  • FileSystemResource:访问文件系统里资源的实现类
  • ServletContextResource:访问相对于ServletContext 路径里的资源的实现类。
  • InputStreamResource:访问输入流资源的实现类。
  • ByteArrayResource:访问字节数组资源的实现类。

9.责任链模式

AOP 的 CglibAopProxy 实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值