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

  • 相关阅读:
    Hard Rock
    Codeforces Round #416 (Div. 2) B. Vladik and Complicated Book
    codeforces 793B. Igor and his way to work
    codeforces 1B Spreadsheets
    HDU 1069 Monkey and Banana
    codeforces 2B The least round way
    【机器学习】 通俗说拟合
    python-八皇后问题
    python-核心知识思维导图
    python-@property 属性
  • 原文地址:https://www.cnblogs.com/wei-zw/p/8797775.html
Copyright © 2011-2022 走看看