zoukankan      html  css  js  c++  java
  • spring mybatis2

    与spring集成,入口:

    SqlSessionFactoryBean实现InitializingBean接口,InitializingBean接口有afterPropertiesSet()方法,(spring的getBean方法里面调进去的)

    SpringApplication.run(MybatisApplication.class, args);
    refreshContext(context);
    super.refresh();
    finishBeanFactoryInitialization(beanFactory);
    beanFactory.preInstantiateSingletons();
    
    getBean(beanName);  //userController
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);    //userController
    populateBean(beanName, mbd, instanceWrapper);     //userController
    pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);      //userService
    getBean(String name)    //userService
    
    beanFactory.getBean(beanName);     //userMapper
    populateBean(beanName, mbd, instanceWrapper);    //userMapper
    Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);    //'sqlSessionTemplate'
    
     getBean(String name)   //funSqlSessionTemplate
    
    getBean(String name)   //funSqlSessionFactory
    SqlSessionFactoryBean类:
    public void setDataSource(DataSource dataSource) {
        if (dataSource instanceof TransactionAwareDataSourceProxy) {  
        } else {
          this.dataSource = dataSource;    //
        }
      }
    
    public SqlSessionFactory getObject() throws Exception {
        if (this.sqlSessionFactory == null) {
          afterPropertiesSet();
        }
        return this.sqlSessionFactory;
      }
    public void afterPropertiesSet() throws Exception {  
        this.sqlSessionFactory = buildSqlSessionFactory();
      }
    protected SqlSessionFactory buildSqlSessionFactory() throws IOException {
        Configuration configuration;
        XMLConfigBuilder xmlConfigBuilder = null;
        if (this.configuration != null) { 
        } else if (this.configLocation != null) { 
        } else { 
          configuration = new Configuration();  //注册别名 
        }   
    
        if (hasLength(this.typeAliasesPackage)) {  //包的别名
          String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage,
              ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);   //typeAliasesPackage = org.study.mybatis.dao.entity,
          for (String packageToScan : typeAliasPackageArray) {
            configuration.getTypeAliasRegistry().registerAliases(packageToScan,
                    typeAliasesSuperType == null ? Object.class : typeAliasesSuperType);    //注册Entity的别名
          }
        }
    
        if (!isEmpty(this.typeAliases)) {   //类型别名
          for (Class<?> typeAlias : this.typeAliases) {
            configuration.getTypeAliasRegistry().registerAlias(typeAlias); 
          }
        }
    
        if (!isEmpty(this.plugins)) {   //插件
          for (Interceptor plugin : this.plugins) {
            configuration.addInterceptor(plugin); 
          }
        }
    
        if (hasLength(this.typeHandlersPackage)) {
          String[] typeHandlersPackageArray = tokenizeToStringArray(this.typeHandlersPackage,
              ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
          for (String packageToScan : typeHandlersPackageArray) {
            configuration.getTypeHandlerRegistry().register(packageToScan); 
          }
        }
    
        if (!isEmpty(this.typeHandlers)) {
          for (TypeHandler<?> typeHandler : this.typeHandlers) {
            configuration.getTypeHandlerRegistry().register(typeHandler); 
          }
        }
    
        if (this.databaseIdProvider != null) {    //多数据源支持
          try {
            configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
          }  
        }
    
        if (this.cache != null) {
          configuration.addCache(this.cache);
        }
    
        if (xmlConfigBuilder != null) {
          try {
            xmlConfigBuilder.parse(); 
          } finally {
            ErrorContext.instance().reset();
          }
        }
    
        if (this.transactionFactory == null) {
          this.transactionFactory = new SpringManagedTransactionFactory();
        }
    
        configuration.setEnvironment(new Environment(this.environment, this.transactionFactory, this.dataSource));
    
        if (!isEmpty(this.mapperLocations)) {   //file [D:acticityvideomybatis-demo-mastermybatis-demo-master	argetclassesmappingUserMapper.xml]
          for (Resource mapperLocation : this.mapperLocations) { 
    
            try {
              XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
                  configuration, mapperLocation.toString(), configuration.getSqlFragments());
              xmlMapperBuilder.parse();
            }  finally {
              ErrorContext.instance().reset();
            } 
          }
        } else { 
        }
    
        return this.sqlSessionFactoryBuilder.build(configuration);
      }
    public void parse() {
        if (!configuration.isResourceLoaded(resource)) {   //resource = file [D:acticityvideomybatis-demo-mastermybatis-demo-master	argetclassesmappingUserMapper.xml]
          configurationElement(parser.evalNode("/mapper"));    //解析XML文件
          configuration.addLoadedResource(resource);
          bindMapperForNamespace();   //Annotation的支持
        }
    
        parsePendingResultMaps();
        parsePendingCacheRefs();
        parsePendingStatements();
      }
    UserMapper.xml:
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="org.study.mybatis.dao.mapper.UserMapper" >
      <resultMap id="BaseResultMap" type="org.study.mybatis.dao.entity.Money" >
        <id column="id" property="id" jdbcType="INTEGER" />
        <result column="name" property="name" jdbcType="VARCHAR" />
        <result column="money" property="money" jdbcType="DOUBLE" />
      </resultMap>
      <sql id="Base_Column_List" >
        id, name, money 
      </sql>
      <select id="list" resultMap="BaseResultMap">
        select <include refid="Base_Column_List"/> from money
      </select>
    </mapper>

     configurationElement(parser.evalNode("/mapper"))

    public XNode evalNode(String expression) {
        return evalNode(document, expression);
      }
    public XNode evalNode(Object root, String expression) {
        Node node = (Node) evaluate(expression, root, XPathConstants.NODE);
        if (node == null) {
          return null;
        }
        return new XNode(this, node, variables);
      }
    private Object evaluate(String expression, Object root, QName returnType) {
        try {
          return xpath.evaluate(expression, root, returnType);
        } 
      }
    private void configurationElement(XNode context) {
        try {
          String namespace = context.getStringAttribute("namespace");   //org.study.mybatis.dao.mapper.UserMapper 
          builderAssistant.setCurrentNamespace(namespace);    //null
          cacheRefElement(context.evalNode("cache-ref"));  //null
          cacheElement(context.evalNode("cache"));  //null
          parameterMapElement(context.evalNodes("/mapper/parameterMap"));  //null
          resultMapElements(context.evalNodes("/mapper/resultMap"));
          sqlElement(context.evalNodes("/mapper/sql"));
          buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
        }  
      }

    context.evalNodes("/mapper/resultMap") 

    //返回<resultMap type="org.study.mybatis.dao.entity.Money" id="BaseResultMap">
    <id jdbcType="INTEGER" column="id" property="id"/>
    <result jdbcType="VARCHAR" column="name" property="name"/>
    <result jdbcType="DOUBLE" column="money" property="money"/>
    </resultMap>

    resultMapElements(context.evalNodes("/mapper/resultMap"));
    private void resultMapElements(List<XNode> list) throws Exception { for (XNode resultMapNode : list) { try { resultMapElement(resultMapNode); } } } private ResultMap resultMapElement(XNode resultMapNode) throws Exception { return resultMapElement(resultMapNode, Collections.<ResultMapping> emptyList()); } private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings) throws Exception { ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier()); String id = resultMapNode.getStringAttribute("id", resultMapNode.getValueBasedIdentifier()); //BaseResultMap String type = resultMapNode.getStringAttribute("type", resultMapNode.getStringAttribute("ofType", resultMapNode.getStringAttribute("resultType", resultMapNode.getStringAttribute("javaType")))); //org.study.mybatis.dao.entity.Money String extend = resultMapNode.getStringAttribute("extends"); //null Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping"); //null Class<?> typeClass = resolveClass(type); //class org.study.mybatis.dao.entity.Money Discriminator discriminator = null; List<ResultMapping> resultMappings = new ArrayList<ResultMapping>(); resultMappings.addAll(additionalResultMappings); List<XNode> resultChildren = resultMapNode.getChildren(); //[<id jdbcType="INTEGER" column="id" property="id"/> , <result jdbcType="VARCHAR" column="name" property="name"/> , <result jdbcType="DOUBLE" column="money" property="money"/> ] for (XNode resultChild : resultChildren) { if ("constructor".equals(resultChild.getName())) { } else if ("discriminator".equals(resultChild.getName())) { } else { List<ResultFlag> flags = new ArrayList<ResultFlag>(); if ("id".equals(resultChild.getName())) { flags.add(ResultFlag.ID); } resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags)); //resultMappings = [ResultMapping{property='id', column='id', javaType=class java.lang.Integer, jdbcType=INTEGER,flags=[ID],lazy=false}, ResultMapping{property='name', column='name', javaType=class java.lang.String, jdbcType=VARCHAR, flags=[], lazy=false}, ResultMapping{property='money', column='money', javaType=double, jdbcType=DOUBLE, flags=[]lazy=false}] } } ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping); // try { return resultMapResolver.resolve(); } } public List<XNode> getChildren() { List<XNode> children = new ArrayList<XNode>(); NodeList nodeList = node.getChildNodes(); //resultMap节点 if (nodeList != null) { for (int i = 0, n = nodeList.getLength(); i < n; i++) { Node node = nodeList.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { children.add(new XNode(xpathParser, node, variables)); } } } return children; //[<id jdbcType="INTEGER" column="id" property="id"/> , <result jdbcType="VARCHAR" column="name" property="name"/> , <result jdbcType="DOUBLE" column="money" property="money"/> ] } public ResultMapResolver(MapperBuilderAssistant assistant, String id, Class<?> type, String extend, Discriminator discriminator, List<ResultMapping> resultMappings, Boolean autoMapping) { this.assistant = assistant; //file [D:acticityvideomybatis-demo-mastermybatis-demo-master argetclassesmappingUserMapper.xml],org.study.mybatis.dao.mapper.UserMapper, this.id = id; //BaseResultMap this.type = type; //class org.study.mybatis.dao.entity.Money this.extend = extend; this.discriminator = discriminator; this.resultMappings = resultMappings; //resultMappings = [ResultMapping{property='id', column='id', javaType=class java.lang.Integer, jdbcType=INTEGER,flags=[ID],lazy=false}, ResultMapping{property='name', column='name', javaType=class java.lang.String, jdbcType=VARCHAR, flags=[], lazy=false}, ResultMapping{property='money', column='money', javaType=double, jdbcType=DOUBLE, flags=[]lazy=false}] this.autoMapping = autoMapping; }
    resultMapResolver.resolve();
    
    public ResultMap resolve() {
        return assistant.addResultMap(this.id, this.type, this.extend, this.discriminator, this.resultMappings, this.autoMapping);
      }
    public ResultMap addResultMap(String id,Class<?> type,String extend, Discriminator discriminator, List<ResultMapping> resultMappings,Boolean autoMapping) {
        id = applyCurrentNamespace(id, false);   //org.study.mybatis.dao.mapper.UserMapper.BaseResultMap
        extend = applyCurrentNamespace(extend, true);   //null
     
        ResultMap resultMap = new ResultMap.Builder(configuration, id, type, resultMappings, autoMapping)
            .discriminator(discriminator).build();
        configuration.addResultMap(resultMap);
        return resultMap;
      }

    sqlElement(context.evalNodes("/mapper/sql"));

    context.evalNodes("/mapper/sql")     //返回<sql id="Base_Column_List">  id, name, money  </sql>
    
    private void sqlElement(List<XNode> list) throws Exception { 
        sqlElement(list, null);
      }
    private void sqlElement(List<XNode> list, String requiredDatabaseId) throws Exception {
        for (XNode context : list) {
          String databaseId = context.getStringAttribute("databaseId");
          String id = context.getStringAttribute("id");    //Base_Column_List
          id = builderAssistant.applyCurrentNamespace(id, false);   //org.study.mybatis.dao.mapper.UserMapper.Base_Column_List
          if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) {
            sqlFragments.put(id, context);   //{org.study.mybatis.dao.mapper.UserMapper.Base_Column_List=<sql id="Base_Column_List"> id, name, money   </sql> , Base_Column_List=<sql id="Base_Column_List">  id, name, money    </sql>
    }
          }
        }
      } 

    buildStatementFromContext(context.evalNodes("select|insert|update|delete"));

    public List<XNode> evalNodes(String expression) {    //expression = select|insert|update|delete
        return xpathParser.evalNodes(node, expression);    //返回<select resultMap="BaseResultMap" id="list"> <include refid="Base_Column_List"/> </select>
      }
    private void buildStatementFromContext(List<XNode> list) {
        if (configuration.getDatabaseId() != null) { 
        }
        buildStatementFromContext(list, null);
      }
    private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) {
        for (XNode context : list) {      //循环所有增删改查语句
          final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId);
          try {
            statementParser.parseStatementNode();
          }  
        }
      }
    public void parseStatementNode() {
        String id = context.getStringAttribute("id");   //list
        String databaseId = context.getStringAttribute("databaseId");   //数据库类型
    
        Integer fetchSize = context.getIntAttribute("fetchSize");
        Integer timeout = context.getIntAttribute("timeout");
        String parameterMap = context.getStringAttribute("parameterMap");
        String parameterType = context.getStringAttribute("parameterType");
        Class<?> parameterTypeClass = resolveClass(parameterType);
        String resultMap = context.getStringAttribute("resultMap");   //BaseResultMap
        String resultType = context.getStringAttribute("resultType");
        String lang = context.getStringAttribute("lang");
        LanguageDriver langDriver = getLanguageDriver(lang);    //
    
        Class<?> resultTypeClass = resolveClass(resultType);
        String resultSetType = context.getStringAttribute("resultSetType");
        StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));    //PREPARED
        ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType);
    
        String nodeName = context.getNode().getNodeName();    //select
        SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));    //SELECT
        boolean isSelect = sqlCommandType == SqlCommandType.SELECT;   //true
        boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);    //false
        boolean useCache = context.getBooleanAttribute("useCache", isSelect);   //true
        boolean resultOrdered = context.getBooleanAttribute("resultOrdered", false);   //false
     
        XMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant);
        includeParser.applyIncludes(context.getNode());
     
        processSelectKeyNodes(id, parameterTypeClass, langDriver);
         
        SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);    //select  id, name, money  from money
        String resultSets = context.getStringAttribute("resultSets");
        String keyProperty = context.getStringAttribute("keyProperty");
        String keyColumn = context.getStringAttribute("keyColumn");
        KeyGenerator keyGenerator;
        String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX;    //list!selectKey
        keyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId, true);   //org.study.mybatis.dao.mapper.UserMapper.list!selectKey,
        if (configuration.hasKeyGenerator(keyStatementId)) { 
        } else {
          keyGenerator = context.getBooleanAttribute("useGeneratedKeys",
              configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType))
              ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
        }
    
        builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
            fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
            resultSetTypeEnum, flushCache, useCache, resultOrdered, 
            keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);  //MappedStatement是跟sql增删改查语句一一对应。
      }
    private void applyIncludes(Node source, final Properties variablesContext, boolean included) {
        if (source.getNodeName().equals("include")) { 
        } else if (source.getNodeType() == Node.ELEMENT_NODE) {
          NodeList children = source.getChildNodes();
          for (int i = 0; i < children.getLength(); i++) {
            applyIncludes(children.item(i), variablesContext, included);
          }
        } else if (included && source.getNodeType() == Node.TEXT_NODE
            && !variablesContext.isEmpty()) { 
          source.setNodeValue(PropertyParser.parse(source.getNodeValue(), variablesContext));
        }
      }
    public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {
        XMLScriptBuilder builder = new XMLScriptBuilder(configuration, script, parameterType);
        return builder.parseScriptNode();
      }
    public SqlSource parseScriptNode() {
        List<SqlNode> contents = parseDynamicTags(context);   //[select , id, name, money ,  from money],动态的,
        MixedSqlNode rootSqlNode = new MixedSqlNode(contents);
        SqlSource sqlSource = null;
        if (isDynamic) {
          sqlSource = new DynamicSqlSource(configuration, rootSqlNode);
        } else {
          sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);
        }
        return sqlSource;  //select  id, name, money  from money
      }

    configuration.addLoadedResource(resource);     //resource = file [D:acticityvideomybatis-demo-mastermybatis-demo-master argetclassesmappingUserMapper.xml]

    bindMapperForNamespace();   //Annotation的支持,SQL语句也可以在注解使用。

    private void bindMapperForNamespace() {
        String namespace = builderAssistant.getCurrentNamespace();    //org.study.mybatis.dao.mapper.UserMapper
        if (namespace != null) {
          Class<?> boundType = null;
          try {
            boundType = Resources.classForName(namespace);   //interface org.study.mybatis.dao.mapper.UserMapper,namespace就是DAO的接口。
          } 
         if (boundType != null) {
            if (!configuration.hasMapper(boundType)) { 
              configuration.addLoadedResource("namespace:" + namespace);    //file [D:acticityvideomybatis-demo-mastermybatis-demo-master	argetclassesmappingUserMapper.xml],namespace:org.study.mybatis.dao.mapper.UserMapper
              configuration.addMapper(boundType);
            }
          }
        }
      }
    public <T> void addMapper(Class<T> type) {
        mapperRegistry.addMapper(type);
      }
    public <T> void addMapper(Class<T> type) {
        if (type.isInterface()) { 
          boolean loadCompleted = false;
          try {
            knownMappers.put(type, new MapperProxyFactory<T>(type));   //knownMappers是缓存,表示已经解析过的,MapperProxyFactory是代理工厂,type=interface org.study.mybatis.dao.mapper.UserMapper。下次就不会进来。
            MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);   //MapperAnnotationBuilder就是对注解的解析。
            parser.parse();
            loadCompleted = true;
          } finally {
            if (!loadCompleted) {
              knownMappers.remove(type);
            }
          }
        }
      }
    public void parse() {
        String resource = type.toString();  //interface org.study.mybatis.dao.mapper.UserMapper
        if (!configuration.isResourceLoaded(resource)) {
          loadXmlResource();
          configuration.addLoadedResource(resource);
          assistant.setCurrentNamespace(type.getName());
          parseCache();
          parseCacheRef();
          Method[] methods = type.getMethods();   //拿到接口的所有方法,
          for (Method method : methods) {   //循环接口的所有方法,
            try { 
              if (!method.isBridge()) {
                parseStatement(method);
              }
            }  
          }
        }
        parsePendingMethods();
      }
    private void parsePendingResultMaps() {
        Collection<ResultMapResolver> incompleteResultMaps = configuration.getIncompleteResultMaps();
        synchronized (incompleteResultMaps) {
          Iterator<ResultMapResolver> iter = incompleteResultMaps.iterator();    //
          while (iter.hasNext()) {
            try {
              iter.next().resolve();
              iter.remove();
            }  
          }
        }
      }
    private void parsePendingCacheRefs() {
        Collection<CacheRefResolver> incompleteCacheRefs = configuration.getIncompleteCacheRefs();
        synchronized (incompleteCacheRefs) {
          Iterator<CacheRefResolver> iter = incompleteCacheRefs.iterator();   //
          while (iter.hasNext()) {
            try {
              iter.next().resolveCacheRef();
              iter.remove();
            }  
          }
        }
      }
    private void parsePendingStatements() {
        Collection<XMLStatementBuilder> incompleteStatements = configuration.getIncompleteStatements();
        synchronized (incompleteStatements) {
          Iterator<XMLStatementBuilder> iter = incompleteStatements.iterator();    //
          while (iter.hasNext()) {
            try {
              iter.next().parseStatementNode();
              iter.remove();
            } 
          }
        }
      }
    return this.sqlSessionFactoryBuilder.build(configuration);
    
    public SqlSessionFactory build(Configuration config) {
        return new DefaultSqlSessionFactory(config);
      }
    上面就是SqlSessionFactoryBean的afterPropertiesSet方法执行,
    回退到:SqlSessionFactoryBean类:
    public void afterPropertiesSet() throws Exception {  
        this.sqlSessionFactory = buildSqlSessionFactory();      //执行到这里完成。
      }
    回退到:SqlSessionFactoryBean类:
    public SqlSessionFactory getObject() throws Exception {
        if (this.sqlSessionFactory == null) {
          afterPropertiesSet();
        }
        return this.sqlSessionFactory;
      }
    回退到:
    bw.setBeanInstance(beanInstance);     //beanInstance = DefaultSqlSessionFactory,
    回退到:
    public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
      }
    回退到:
    MapperFactoryBean实例化。调用MapperFactoryBean的getObject(),
    回退到:
    exposedObject = initializeBean(beanName, exposedObject, mbd);    //beanName = userMapper
    回退到:
    exposedObject = initializeBean(beanName, exposedObject, mbd);      //beanName = userService
    回退到:
    exposedObject = initializeBean(beanName, exposedObject, mbd);    //beanName = userController
    初始化过程完毕。
  • 相关阅读:
    学到了林海峰,武沛齐讲的Day63 网页制作思路 Toando 自定义form验证
    学到了林海峰,武沛齐讲的Day62 SONP实现AJax跨域 Iframe文件上传
    学到了林海峰,武沛齐讲的Day60 Form组件中的源码添加详解 gjango序列化 数据库取值转换
    学到了林海峰,武沛齐讲的Day59 Form组件
    学到了林海峰,武沛齐讲的Day58 分页 初识Form
    学到了林海峰,武沛齐讲的Day57 表单实战讲解
    学到了林海峰,武沛齐讲的Day56 表单实战讲解
    学到了林海峰,武沛齐讲的Day58 分页 form表单
    最详细的正则(转载)
    爬虫笔记(二):爬取药监局所有详情页数据
  • 原文地址:https://www.cnblogs.com/yaowen/p/12349919.html
Copyright © 2011-2022 走看看