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是通过一个工厂方法创建的,具体的流程如下图所示:

SqlMapClient 在Spring中创建过程_第1张图片
 

通过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 一个新的对象。

 

你可能感兴趣的:(SqlMapClient 在Spring中创建过程)