博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring中使用的九种设计模式
阅读量:6229 次
发布时间:2019-06-21

本文共 6954 字,大约阅读时间需要 23 分钟。

Spring框架是每个java程序猿入门级的框架也是最重要的框架,而Spring中也采用了很多的设计模式,这些也会成为我们面试过程中经常会问到的问题,所以本文就整理出Spring中具体使用的哪些设计模式。 Spring使用的设计模式

1.单例模式

单例模式应该是大家印象最深的一种设计模式了。在Spring中最明显的使用场景是在配置文件中配置注册bean对象的时候设置scope的值为singleton。

复制代码

源码实现:AbstractBeanFactory的getBean方法中

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 != NULL_OBJECT ? singletonObject : null);}复制代码

双重判断加锁的实现!!!

2.原型模式

原型模式也叫克隆模式,Spring中该模式使用的很明显,和单例一样在bean标签中设置scope的属性为prototype即表示该bean以克隆的方式生成

复制代码

3.模板模式

模板模式的核心是父类定义好流程,然后将流程中需要子类实现的方法就抽象话留给子类实现,Spring中的JdbcTemplate就是这样的实现。我们知道jdbc的步骤是固定的(

加载驱动,

  1. 获取连接通道,
  2. 构建sql语句.
  3. 执行sql语句,
  4. 关闭资源,   在这些步骤中第3步和第四步是不确定的,所以就留给客户实现,而我们实际使用JdbcTemplate的时候也确实是只需要构建SQL就可以了.这就是典型的模板模式。我们以query方法为例来看下JdbcTemplate中的代码
// 在execute方法中定义好了jdbc操作的流程// action.doInStatement(stmtToUse);是回调方法也就是钩子@Overridepublic 
T execute(StatementCallback
action) throws DataAccessException { Assert.notNull(action, "Callback object must not be null"); Connection con = DataSourceUtils.getConnection(getDataSource()); Statement stmt = null; try { Connection conToUse = con; if (this.nativeJdbcExtractor != null && this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) { conToUse = this.nativeJdbcExtractor.getNativeConnection(con); } stmt = conToUse.createStatement(); applyStatementSettings(stmt); Statement stmtToUse = stmt; if (this.nativeJdbcExtractor != null) { stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt); } T result = action.doInStatement(stmtToUse); handleWarnings(stmt); return result; } catch (SQLException ex) { // Release Connection early, to avoid potential connection pool deadlock // in the case when the exception translator hasn't been initialized yet. JdbcUtils.closeStatement(stmt); stmt = null; DataSourceUtils.releaseConnection(con, getDataSource()); con = null; throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex); } finally { JdbcUtils.closeStatement(stmt); DataSourceUtils.releaseConnection(con, getDataSource()); }}复制代码

query方法

@Overridepublic 
T query(final String sql, final ResultSetExtractor
rse) throws DataAccessException { Assert.notNull(sql, "SQL must not be null"); Assert.notNull(rse, "ResultSetExtractor must not be null"); if (logger.isDebugEnabled()) { logger.debug("Executing SQL query [" + sql + "]"); } // 实现模板中预留的功能 class QueryStatementCallback implements StatementCallback
, SqlProvider { @Override public T doInStatement(Statement stmt) throws SQLException { ResultSet rs = null; try { // 此处具体执行查询操作 rs = stmt.executeQuery(sql); ResultSet rsToUse = rs; if (nativeJdbcExtractor != null) { rsToUse = nativeJdbcExtractor.getNativeResultSet(rs); } // 处理数据封装操作 return rse.extractData(rsToUse); } finally { JdbcUtils.closeResultSet(rs); } } @Override public String getSql() { return sql; } } return execute(new QueryStatementCallback());}复制代码

4.观察者模式

观察者模式定义的是对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。使用比较场景是在监听器中而spring中Observer模式常用的地方也是listener的实现。如ApplicationListener。 Spring中的事件监听请参考我的另一篇文章 Spring之事件监听(观察者模型)

5.工厂模式

简单工厂模式

简单工厂模式就是通过工厂根据传递进来的参数决定产生哪个对象。Spring中我们通过getBean方法获取对象的时候根据id或者name获取就是简单工厂模式了。

复制代码

工厂方法模式

在Spring中我们一般是将Bean的实例化直接交给容器去管理的,实现了使用和创建的分离,这时容器直接管理对象,还有种情况是,bean的创建过程我们交给一个工厂去实现,而Spring容器管理这个工厂。这个就是我们讲的工厂模式,在Spring中有两种实现一种是静态工厂方法模式,一种是动态工厂方法模式。以静态工厂来演示

/** * User 工厂类 * @author dpb[波波烤鸭] * */public class UserFactory {	/**	 * 必须是static方法	 * @return	 */	public static UserBean getInstance(){		return new UserBean();	}}复制代码

application.xml文件中注册

复制代码

6.适配器模式

将一个类的接口转换成客户希望的另外一个接口。使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。这就是适配器模式。在Spring中在AOP实现中的Advice和interceptor之间的转换就是通过适配器模式实现的。

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {	@Override	public boolean supportsAdvice(Advice advice) {		return (advice instanceof MethodBeforeAdvice);	}	@Override	public MethodInterceptor getInterceptor(Advisor advisor) {		MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();		// 通知类型匹配对应的拦截器		return new MethodBeforeAdviceInterceptor(advice);	}}复制代码

详细介绍可以参考此文Spring之AOP适配器模式

7.装饰者模式

装饰者模式又称为包装模式(Wrapper),作用是用来动态的为一个对象增加新的功能。装饰模式是一种用于代替继承的技术,无须通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。   spring中用到的包装器模式在类名上有两种表现:一种是类名中含有Wrapper,另一种是类名中含有Decorator。基本上都是动态地给一个对象添加一些额外的职责。   具体的使用在Spring session框架中的SessionRepositoryRequestWrapper使用包装模式对原生的request的功能进行增强,可以将session中的数据和分布式数据库进行同步,这样即使当前tomcat崩溃,session中的数据也不会丢失。

查看需要的maven依赖

org.springframework.session
spring-session
1.3.1.RELEASE
复制代码

8.代理模式

代理模式应该是大家非常熟悉的设计模式了,在Spring中AOP的实现中代理模式使用的很彻底,如果不了解代理模式欢迎查看我之前的文章,链接在顶部。

9.策略模式

策略模式对应于解决某一个问题的一个算法族,允许用户从该算法族中任选一个算法解决某一问题,同时可以方便的更换算法或者增加新的算法。并且由客户端决定调用哪个算法,spring中在实例化对象的时候用到Strategy模式。

@Overridepublic Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {	// Don't override the class with CGLIB if no overrides.	if (bd.getMethodOverrides().isEmpty()) {		Constructor
constructorToUse; synchronized (bd.constructorArgumentLock) { constructorToUse = (Constructor
) bd.resolvedConstructorOrFactoryMethod; if (constructorToUse == null) { final Class
clazz = bd.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { if (System.getSecurityManager() != null) { constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction
>() { @Override public Constructor
run() throws Exception { return clazz.getDeclaredConstructor((Class[]) null); } }); } else { constructorToUse = clazz.getDeclaredConstructor((Class[]) null); } bd.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Throwable ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } } return BeanUtils.instantiateClass(constructorToUse); } else { // Must generate CGLIB subclass. return instantiateWithMethodInjection(bd, beanName, owner); }}复制代码

转载于:https://juejin.im/post/5cb9ca94f265da0387339c6f

你可能感兴趣的文章
iPhone 6/plus iOS Safari fieldset border 边框消失
查看>>
Xms Xmx PermSize MaxPermSize 区别
查看>>
【转】预装(push)lib64中so文件查找错误
查看>>
《Python简明教程》总结
查看>>
构造 - HDU 5402 Travelling Salesman Problem
查看>>
[转]图解分布式一致性协议Paxos
查看>>
【SSH2(实用文章)】--Struts2文件上传和下载的例子
查看>>
Rust初步(七):格式化
查看>>
微服务架构的设计模式
查看>>
【C++】继承时构造函数和析构函数
查看>>
python风味之大杂烩
查看>>
NSDate & NSDateFormatter
查看>>
android 点击屏幕关闭 软键盘
查看>>
相似图片搜索的原理(转)
查看>>
钟南山:高收入群体往往老得快
查看>>
Linux Kernel(Android) 加密算法汇总(三)-应用程序调用内核加密算法接口
查看>>
开发中三个经典的原则
查看>>
logging日志管理-将日志写入文件
查看>>
Hibernate 、Hql查询和Criteria查询
查看>>
滚动条滚动到底部触发事件
查看>>