zoukankan      html  css  js  c++  java
  • Spring中使用的设计模式

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


    Java单例模式
    Java原型模式(prototype)
    Java模板模式(template)
    Java观察者模式(Observer)
    Java工厂模式
    Java适配器模式(adapter)
    Java装饰者模式(decorator)
    Java代理模式
    Java策略模式(Strategy)


    @

    Spring使用的设计模式

    1.单例模式

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

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd">
    	<bean class="com.dpb.pojo.User" id="user" scope="singleton">
    		<property name="name" value="波波烤鸭"></property>
    	</bean>
    </beans>
    

    源码实现: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以克隆的方式生成

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd">
    	<bean class="com.dpb.pojo.User" id="user" scope="prototype">
    		<property name="name" value="波波烤鸭"></property>
    	</bean>
    </beans>
    

    3.模板模式

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

    1. 加载驱动,
    2. 获取连接通道,
    3. 构建sql语句.
    4. 执行sql语句,
    5. 关闭资源),

      在这些步骤中第3步和第四步是不确定的,所以就留给客户实现,而我们实际使用JdbcTemplate的时候也确实是只需要构建SQL就可以了.这就是典型的模板模式。我们以query方法为例来看下JdbcTemplate中的代码

    // 在execute方法中定义好了jdbc操作的流程
    // action.doInStatement(stmtToUse);是回调方法也就是钩子
    @Override
    public <T> T execute(StatementCallback<T> 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方法

    @Override
    public <T> T query(final String sql, final ResultSetExtractor<T> 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<T>, 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获取就是简单工厂模式了。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
    	
    	<context:annotation-config/>
    	<bean class="com.dpb.pojo.User" id="user"  >
    		<property name="name" value="波波烤鸭"></property>
    	</bean>
    </beans>
    

    工厂方法模式

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

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

    application.xml文件中注册

    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans 
    	http://www.springframework.org/schema/beans/spring-beans.xsd">
    	<!-- 静态工厂方式配置 配置静态工厂及方法 -->
    	<bean class="com.dpb.factory.UserFactory" factory-method="getInstance" id="user2"/>
    </beans>
    

    在这里插入图片描述

    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依赖

    <dependency>
    	<groupId>org.springframework.session</groupId>
    	<artifactId>spring-session</artifactId>
    	<version>1.3.1.RELEASE</version>
    </dependency>
    

    8.代理模式

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

    9.策略模式

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

    @Override
    public 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<Constructor<?>>() {
    							@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);
    	}
    }
    
  • 相关阅读:
    C++笔记(2018/2/6)
    2017级面向对象程序设计寒假作业1
    谁是你的潜在朋友
    A1095 Cars on Campus (30)(30 分)
    A1083 List Grades (25)(25 分)
    A1075 PAT Judge (25)(25 分)
    A1012 The Best Rank (25)(25 分)
    1009 说反话 (20)(20 分)
    A1055 The World's Richest(25 分)
    A1025 PAT Ranking (25)(25 分)
  • 原文地址:https://www.cnblogs.com/dengpengbo/p/10485924.html
Copyright © 2011-2022 走看看