Spring中用到的设计模式

目录

​编辑

0.Spring中用到的设计模式:

1.模板模式

1.JDK->AQS,基于AQS创建锁

2.Spring IOC容器的初始化

3.Spring 依赖注入(IOC 控制反转):

4.Spring AOP:

5.SpringMVC:

6.SpringSecurity:

7.观察者模式

8.发布订阅模式

9策略模式

10.建造者模式

11.装饰器模式:


0.Spring中用到的设计模式:

其实只要答出下面的几种就行了:

1.模板模式

1.JDK->AQS,基于AQS创建锁

AbstractQueuedSynchronizer:抽象类,AQS框架核心类,其内部以虚拟队列的方式管理线程的锁获取与锁释放,其中获取锁(tryAcquire方法)和释放锁(tryRelease方法)并没有提供默认实现,需要子类重写这两个方法实现具体逻辑,目的是使开发人员可以自由定义获取锁以及释放锁的方式。

这个抽象类提供了两个钩子方法tryAcquire(int arg)与tryRelease(int arg), 需要子类去实现。 从设计模式角度来看,AQS采用的模板模式的方式构建的,其内部除了提供并发操作核心方法以及同步队列操作外,还提供了一些模板方法让子类自己实现,如加锁操作以及解锁操作,为什么这么做?这是因为AQS作为基础组件,封装的是核心并发操作,但是实现上分为两种模式,即共享模式独占模式,而这两种模式的加锁与解锁实现方式是不一样的,但AQS只关注内部公共方法实现并不关心外部不同模式的实现,所以提供了模板方法给子类使用,也就是说实现独占锁,如ReentrantLock需要自己实现tryAcquire()方法和tryRelease()方法,而实现共享模式的Semaphore,则需要实现tryAcquireShared()方法和tryReleaseShared()方法,这样做的好处是显而易见的,无论是共享模式还是独占模式,其基础的实现都是同一套组件(AQS),只不过是加锁解锁的逻辑不同罢了,更重要的是如果我们需要自定义锁的话,也变得非常简单,只需要选择不同的模式实现不同的加锁和解锁的模板方法即可

2.Spring IOC容器的初始化

Spring IOC容器的初始化过程->AbstractApplicationContext.java抽象类 -> refresh()方法,就是一个模板方法。

AbstractApplicationContext.java抽象类 -> refresh()方法 -> postProcessBeanFactory(beanFactory),是一个钩子方法,一个空方法,没有实现任何功能,由子类根据情况去实现。

AbstractApplicationContext.java抽象类 -> refresh()方法 -> onRefresh(),也是一个钩子方法,一个空方法,没有实现任何功能,由子类根据情况去实现。

子类的实现:

ConfigurableApplicationContext.java(接口) -> AbstractApplicationContext(实现了ConfigurableApplicationContext.java) -> GenericApplicationContext.java(继承了AbstractApplicationContext)

  1. 抽象模板类 -> 模板方法 -> 模板方法调用普通方法,抽象方法,钩子方法。
  2. 子类继承抽象模板类 -> 实现抽象方法,钩子方法

我们常用的创建IOC容器的AnnotationConfigWebApplicationContextClassPathXmlApplicationContext类,最终都是继承于AbstractApplicationContext.java抽象类

还有jdbcTemplate:

3.Spring 依赖注入(IOC 控制反转):

Spring依赖注入有两种方式,单例和prototype,分别用到了单例模式原型模式

原型模式:使用原型模式创建对象比直接new一个对象在性能上好得多,因为Object类的clone()方法是一个native方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显,但是Object.clone()不能够深拷贝,只能浅拷贝,所以如果一个对象中有引用类型的属性,那么就需要用序列化,反序列化的方式去完成(字节流???)

简单工厂:Spring中BeanFactory就是工厂模式的提现,根据传入一个唯一的标识来获得Bean对象;

模板模式:在各种BeanFactory以及ApplicationContext实现中用到了;

4.Spring AOP:

AOP具体是由动态代理实现的,动态代理模式。动态代理底层用到了反射。

JDK动态代理与CGlib的区别:JDK动态代理只能代理实现了接口的类,动态代理会实现该接口的方法,在该方法中调用被代理对象的相同方法(会将该对象赋值给其对应的接口(父类引用指向子类实现))。而Cglib类似于继承,动态代理类作为一个子类,重写了父类(被代理类)的方法,别重写的方法中,调用了父类的相同方法。

5.SpringMVC:

责任链模式和适配器模式

java8中的stream流式编程也类似于责任链模式。

springMVC中定义的拦截器,多个拦截器组成一个拦截器链,责任链模式

6.SpringSecurity:

深入理解Spring Security之过滤器责任链模式分析_李永志的博客-CSDN博客

责任链模式:

Spring Security 中的过滤器链就是一种责任链模式。一个请求到达后,被过滤器链中的过滤器逐个进行处理,过滤器链中的过滤器每个都具有不同的职能并且互不相扰,我们还可以通过 HttpSecurity 来动态配置过滤器链中的过滤器(即添加/删除过滤器链中的过滤器)。

  @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                ....
                //在这里添加了过滤器,这里指定了配置过滤器并且配置的位置
               .addFilterBefore(singleSignOutFilter, CasAuthenticationFilter.class)
    }

SpringCloud gateway中的过滤器链,也是责任链模式,过滤器链中的每个过滤器都可以对http request做处理,例如登录验证、对http header,parameter,path,response等的处理。

参考文章:springCloud-13 gateWay过滤器:概述_vegetari的博客-CSDN博客_springcloud过滤器 

7.观察者模式

springboot启动过程(run方法)中的监听器 ,在SpringApplication的构造方法中,会从spring.factories文件中加载所有的监听器(共有11个,使用反射生产监听器对象)。构造完成后会调用run方法,会再次从spring.factories文件中加载监听器的事件发布器(监听器是观察者,事件发布器是被观察者),事件发布器会获取之前加载的11个监听器,然后放到自己的集合里,然后这个事件发布器会在springboot启动过程中,发布各种事件,例如starting,环境变量prepared,before refreshcontext,启动结束事件,发布给监听器去处理,比如回收资源等。

总之:监听器会监听springboot启动过程中,所有的事件

如果在自己的工程中,自定义监听器,则需要将自定义的监听器加入到本工程 resources  \META-INF/spring.factories 文件中

运行结果: 

 关于监听器,请看文章:Spring之事件监听(观察者模型)_波波烤鸭的博客-CSDN博客_spring 观察者

8.发布订阅模式

MQ, 注册中心,发布订阅模式与观察者模式类似,但是不同之处在于,发布订阅模式实现了观察者与被观察者(时间发布者)的解耦,二者不产生直接联系。但是观察者模式,观察者要注册到被观察者中。

9策略模式

1.AnnotationConfigWebApplicationContext, ClassPathXmlApplicationContext等根据xml或者注解进行处理的spring容器

2.XmlBeanDefinitionReader, PropertiesBeanDefinitionReader等根据不同情况加载bean配置的类。

BeanDefinitionReader 是 Spring 容器中提供的 BeanDefinition 读取器,用于将 Spring 的配置信息,转换为 BeanDefinition 。提供了4个实现类:

  • AbstractBeanDefinitionReader:是一个抽象类,同时实现了 EnvironmentCapable 接口,提供环境的get和set方法。它实现了BeanDefinitionReader 的一些通用方法,比如按照路径来读取 Bean 定义信息的方法→int loadBeanDefinitions(String location)。对于更为具体的方法,比如根据资源来读取 Bean 定义信息的方法→int loadBeanDefinitions(Resource resource), 则交由子类来实现。
  • PropertiesBeanDefinitionReader:是一个具体实现类,可以从properties文件读取Bean定义信息。
  • XmlBeanDefinitionReader:具体实现类,可以从XML文件读取Bean定义信息。
  • GroovyBeanDefinitionReader:具体实现类,可以读取Groovy 语言写的Bean的定义信息。

这些 BeanDefinitionReader 在我们使用 Spring 开的时候较少使用,在 Spring 源码中使用的比较多,相当于是 Spring 内部的基础设施。

3.其它策略模式:Java要求如果定义的复合对象要有排序的功能,就自行实现Comparable接口或Comparator接口;

10.建造者模式

mybatis的sqlSessionFactory,要得到这个对象,需要解析属性文件和映射文件,非常复杂,而mybatis给我们提供了建造者模式,屏蔽了构建这个对象的复杂操作,用户可以直接通过new得到这个对象。当然了这个对象还是一个工厂模式。

11.装饰器模式:

1. 文件IO涉及到的各种输入输出流,最基本的输入输出流,可以被简单包装一下,生成别种类型的输入输出流。

public class ContextHolder {

	try (ZipInputStream zip = new ZipInputStream(new FileInputStream(...))) {
		ZipEntry entry = null;
		while ((entry = zip.getNextEntry()) != null) {
			String name = entry.getName();
			if (!entry.isDirectory()) {
				int n;
				while ((n = zip.read()) != -1) {
					...
				}
			}
		}
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值