zoukankan      html  css  js  c++  java
  • SqlMapClient 在Spring中创建过程

         在Spring中集成iBATIS是一件很简单的事情,只需要简单的配置即可;在Spring中使用iBATIS的配置如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jee="http://www.springframework.org/schema/jee"
    	xmlns:task="http://www.springframework.org/schema/task"
    	xsi:schemaLocation="
    		http://www.springframework.org/schema/beans
    		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    		http://www.springframework.org/schema/context
    		http://www.springframework.org/schema/context/spring-context-3.0.xsd
    		http://www.springframework.org/schema/aop 
    		http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    		http://www.springframework.org/schema/tx
    		http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    		http://www.springframework.org/schema/jee 
    		http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
    		http://www.springframework.org/schema/task  
            http://www.springframework.org/schema/task/spring-task-3.1.xsd  
    		">
    	<context:component-scan base-package="com.david.*" />
    	<aop:aspectj-autoproxy />
    	<context:property-placeholder location="classpath:META-INF/config.properties" />
    	<!-- 定义数据源 -->
    	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    		destroy-method="close">
    		<property name="driverClass" value="${jdbc.ams.driver}" />
    		<property name="jdbcUrl" value="${jdbc.ams.url}" />
    		<property name="user" value="${jdbc.ams.username}" />
    		<property name="password" value="${jdbc.ams.password}" />
    		<property name="initialPoolSize" value="${initialSize}" />
    		<property name="minPoolSize" value="${minPoolSize}" />
    		<property name="maxPoolSize" value="${maxActive}" />
    		<property name="acquireIncrement" value="${acquireIncrement}" />
    		<property name="maxIdleTime" value="${maxIdleTime}" />
    	</bean>
    
    	<!-- 定义jdbc模板类 -->
    	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    		<property name="dataSource" ref="dataSource" />
    	</bean>
    
    	<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
    		<property name="dataSource" ref="dataSource" />
    		<property name="configLocation" value="classpath:META-INF/sqlmap/sqlmap.xml" />
    	</bean>
    	<bean id="transactionManager"
    		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    		<property name="dataSource" ref="dataSource" />
    	</bean>
    
    	<tx:annotation-driven transaction-manager="transactionManager" />

     我们知道SqlMapClientImpl实例是iBTATIS的门面,所有的操作都是调用client的方法,那么SqlMapClient的实例又是如何,在什么地方被创建的呢?

       我们通过配置文件可以发现,client是通过一个工厂方法创建的,具体的流程如下图所示:


     

    通过SqlMapClientFactoryBean源码可以发现,该类实现了InitializingBean

    public class SqlMapClientFactoryBean implements FactoryBean<SqlMapClient>, InitializingBean {

     这个接口的作用又是什么呢?可以看看该接口的注释:

    /**
      * Invoked by a BeanFactory after it has set all bean properties supplied
      * (and satisfied BeanFactoryAware and ApplicationContextAware).
      * <p>This method allows the bean instance to perform initialization only
      * possible when all bean properties have been set and to throw an
      * exception in the event of misconfiguration.
      * @throws Exception in the event of misconfiguration (such
      * as failure to set an essential property) or if initialization fails.
      */
     void afterPropertiesSet() throws Exception;
    

    一个类实现了这个接口就会在所有属性初始化完成后,调用afterPropertiesSet()方法,而SqlMapClientFactoryBean正是在这个方法中进行SqlMapClientImpl的实例初始化。

    	public void afterPropertiesSet() throws Exception {
    		if (this.lobHandler != null) {
    			// Make given LobHandler available for SqlMapClient configuration.
    			// Do early because because mapping resource might refer to custom types.
    			configTimeLobHandlerHolder.set(this.lobHandler);
    		}
    
    		try {
    			this.sqlMapClient = buildSqlMapClient(this.configLocations, this.mappingLocations, this.sqlMapClientProperties);
    
    			// Tell the SqlMapClient to use the given DataSource, if any.
    			if (this.dataSource != null) {
    				TransactionConfig transactionConfig = (TransactionConfig) this.transactionConfigClass.newInstance();
    				DataSource dataSourceToUse = this.dataSource;
    				if (this.useTransactionAwareDataSource && !(this.dataSource instanceof TransactionAwareDataSourceProxy)) {
    					dataSourceToUse = new TransactionAwareDataSourceProxy(this.dataSource);
    				}
    				transactionConfig.setDataSource(dataSourceToUse);
    				transactionConfig.initialize(this.transactionConfigProperties);
    				applyTransactionConfig(this.sqlMapClient, transactionConfig);
    			}
    		}
    
    		finally {
    			if (this.lobHandler != null) {
    				// Reset LobHandler holder.
    				configTimeLobHandlerHolder.remove();
    			}
    		}
    	}
    
    	/**
    	 * Build a SqlMapClient instance based on the given standard configuration.
    	 * <p>The default implementation uses the standard iBATIS {@link SqlMapClientBuilder}
    	 * API to build a SqlMapClient instance based on an InputStream (if possible,
    	 * on iBATIS 2.3 and higher) or on a Reader (on iBATIS up to version 2.2).
    	 * @param configLocations the config files to load from
    	 * @param properties the SqlMapClient properties (if any)
    	 * @return the SqlMapClient instance (never <code>null</code>)
    	 * @throws IOException if loading the config file failed
    	 * @see com.ibatis.sqlmap.client.SqlMapClientBuilder#buildSqlMapClient
    	 */
    	protected SqlMapClient buildSqlMapClient(
    			Resource[] configLocations, Resource[] mappingLocations, Properties properties)
    			throws IOException {
    
    		if (ObjectUtils.isEmpty(configLocations)) {
    			throw new IllegalArgumentException("At least 1 'configLocation' entry is required");
    		}
    
    		SqlMapClient client = null;
    		SqlMapConfigParser configParser = new SqlMapConfigParser();
    		for (Resource configLocation : configLocations) {
    			InputStream is = configLocation.getInputStream();
    			try {
    				client = configParser.parse(is, properties);
    			}
    			catch (RuntimeException ex) {
    				throw new NestedIOException("Failed to parse config resource: " + configLocation, ex.getCause());
    			}
    		}
    
    		if (mappingLocations != null) {
    			SqlMapParser mapParser = SqlMapParserFactory.createSqlMapParser(configParser);
    			for (Resource mappingLocation : mappingLocations) {
    				try {
    					mapParser.parse(mappingLocation.getInputStream());
    				}
    				catch (NodeletException ex) {
    					throw new NestedIOException("Failed to parse mapping resource: " + mappingLocation, ex);
    				}
    			}
    		}
    
    		return client;
    	}

     跟踪代码就可以发现其后的初始化就是一层层new 一个新的对象。

  • 相关阅读:
    窗口和消息
    输出文字
    《windows程序设计》第一章,建议想学API的每天看一章
    hdu 1008为何不对?求大神指导!
    课程设计(物体类),图片可能没有加载出来,自己运行一下就行了
    二叉树前序、中序、后序遍历相互求法
    哈希表工作原理
    c++中关于static关键字的问题
    Halcon学习笔记之缺陷检测(二)
    Halcon学习笔记之缺陷检测(一)
  • 原文地址:https://www.cnblogs.com/wei-zw/p/8797775.html
Copyright © 2011-2022 走看看