zoukankan      html  css  js  c++  java
  • Spring-MongoDB 关键类的源码分析

    本文分析的是 spring-data-mongodb-1.9.2.RELEASE.jar 和 mongodb-driver-core-3.2.2.jar。

    一、UML Class Diagram

    核心类是 MongoTemplate,下面这张 UML 类图涉及了主要的类,省略了次要的类。

    涉及的类: MongoTemplate,

    MongoOperations,

    MongoDbFactory,

    SimpleMongoDbFactory,

    Mongo,

    MongoClient,

    MongoCredential,

    ServerAddress。

    二、源码分析

     (1) MongoTemplate

    MongoTemplate 是 Spring-MongoDB 整合的核心类,它实现了 MongoOperations 接口(该接口定义了 CRUD 操作)。

    MongoTemplate 有个核心的构造方法(其他重载的构造方法最终都会调用这个构造方法):

        /**
         * Constructor used for a basic template configuration.
         * 
         * @param mongoDbFactory must not be {@literal null}.
         * @param mongoConverter
         */
        public MongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter mongoConverter) {
    
            Assert.notNull(mongoDbFactory);
    
            this.mongoDbFactory = mongoDbFactory;
            this.exceptionTranslator = mongoDbFactory.getExceptionTranslator();
            this.mongoConverter = mongoConverter == null ? getDefaultMongoConverter(mongoDbFactory) : mongoConverter;
            this.queryMapper = new QueryMapper(this.mongoConverter);
            this.updateMapper = new UpdateMapper(this.mongoConverter);
    
            // We always have a mapping context in the converter, whether it's a simple one or not
            mappingContext = this.mongoConverter.getMappingContext();
            // We create indexes based on mapping events
            if (null != mappingContext && mappingContext instanceof MongoMappingContext) {
                indexCreator = new MongoPersistentEntityIndexCreator((MongoMappingContext) mappingContext, mongoDbFactory);
                eventPublisher = new MongoMappingEventPublisher(indexCreator);
                if (mappingContext instanceof ApplicationEventPublisherAware) {
                    ((ApplicationEventPublisherAware) mappingContext).setApplicationEventPublisher(eventPublisher);
                }
            }
        }

    可以看到,这个构造方法至少需要一个参数 mongoDbFactory,MongoTemplate 类中其他字段都可以内部构造出来。

    (2)MongoDbFactory

    MongoDbFactory 是一个接口,用于新建 DB 实例。

    它的实现之一是 SimpleMongoDbFactory。

    public interface MongoDbFactory {
    
        /**
         * Creates a default {@link DB} instance.
         * 
         * @return
         * @throws DataAccessException
         */
        DB getDb() throws DataAccessException;
    
        /**
         * Creates a {@link DB} instance to access the database with the given name.
         * 
         * @param dbName must not be {@literal null} or empty.
         * @return
         * @throws DataAccessException
         */
        DB getDb(String dbName) throws DataAccessException;
    
        /**
         * Exposes a shared {@link MongoExceptionTranslator}.
         * 
         * @return will never be {@literal null}.
         */
        PersistenceExceptionTranslator getExceptionTranslator();
    }

    (3) SimpleMongoDbFactory

    SimpleMongoDbFactory 实现了 MongoDbFactory 接口(以下省略了部分代码):

     1 public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
     2 
     3     private final Mongo mongo;
     4     private final String databaseName;
     5     private final boolean mongoInstanceCreated;
     6     private final UserCredentials credentials;
     7     private final PersistenceExceptionTranslator exceptionTranslator;
     8     private final String authenticationDatabaseName;
     9 
    10     private WriteConcern writeConcern;
    11     
    12     /**
    13      * Creates a new {@link SimpleMongoDbFactory} instance from the given {@link MongoClientURI}.
    14      * 
    15      * @param uri must not be {@literal null}.
    16      * @throws UnknownHostException
    17      * @since 1.7
    18      */
    19     public SimpleMongoDbFactory(MongoClientURI uri) throws UnknownHostException {
    20         this(new MongoClient(uri), uri.getDatabase(), true);
    21     }
    22 
    23     /**
    24      * Creates a new {@link SimpleMongoDbFactory} instance from the given {@link MongoClient}.
    25      * 
    26      * @param mongoClient must not be {@literal null}.
    27      * @param databaseName must not be {@literal null}.
    28      * @since 1.7
    29      */
    30     public SimpleMongoDbFactory(MongoClient mongoClient, String databaseName) {
    31         this(mongoClient, databaseName, false);
    32     }
    33 
    34     private SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials credentials,
    35             boolean mongoInstanceCreated, String authenticationDatabaseName) {
    36 
    37         if (mongo instanceof MongoClient && (credentials != null && !UserCredentials.NO_CREDENTIALS.equals(credentials))) {
    38             throw new InvalidDataAccessApiUsageException(
    39                     "Usage of 'UserCredentials' with 'MongoClient' is no longer supported. Please use 'MongoCredential' for 'MongoClient' or just 'Mongo'.");
    40         }
    41 
    42         Assert.notNull(mongo, "Mongo must not be null");
    43         Assert.hasText(databaseName, "Database name must not be empty");
    44         Assert.isTrue(databaseName.matches("[\w-]+"),
    45                 "Database name must only contain letters, numbers, underscores and dashes!");
    46 
    47         this.mongo = mongo;
    48         this.databaseName = databaseName;
    49         this.mongoInstanceCreated = mongoInstanceCreated;
    50         this.credentials = credentials == null ? UserCredentials.NO_CREDENTIALS : credentials;
    51         this.exceptionTranslator = new MongoExceptionTranslator();
    52         this.authenticationDatabaseName = StringUtils.hasText(authenticationDatabaseName) ? authenticationDatabaseName
    53                 : databaseName;
    54 
    55         Assert.isTrue(this.authenticationDatabaseName.matches("[\w-]+"),
    56                 "Authentication database name must only contain letters, numbers, underscores and dashes!");
    57     }
    58 
    59     /**
    60      * @param client
    61      * @param databaseName
    62      * @param mongoInstanceCreated
    63      * @since 1.7
    64      */
    65     private SimpleMongoDbFactory(MongoClient client, String databaseName, boolean mongoInstanceCreated) {
    66 
    67         Assert.notNull(client, "MongoClient must not be null!");
    68         Assert.hasText(databaseName, "Database name must not be empty!");
    69 
    70         this.mongo = client;
    71         this.databaseName = databaseName;
    72         this.mongoInstanceCreated = mongoInstanceCreated;
    73         this.exceptionTranslator = new MongoExceptionTranslator();
    74         this.credentials = UserCredentials.NO_CREDENTIALS;
    75         this.authenticationDatabaseName = databaseName;
    76     }
    77 
    78 }

    核心构造方法:

    /**
         * @param client
         * @param databaseName
         * @param mongoInstanceCreated
         * @since 1.7
         */
        private SimpleMongoDbFactory(MongoClient client, String databaseName, boolean mongoInstanceCreated) {
    
            Assert.notNull(client, "MongoClient must not be null!");
            Assert.hasText(databaseName, "Database name must not be empty!");
    
            this.mongo = client;
            this.databaseName = databaseName;
            this.mongoInstanceCreated = mongoInstanceCreated;
            this.exceptionTranslator = new MongoExceptionTranslator();
            this.credentials = UserCredentials.NO_CREDENTIALS;
            this.authenticationDatabaseName = databaseName;
        }

    第一个参数 MongoClient client(MongoClient): 包含 host, port, username, password 等信息。

    (4)MongoClient 与 Mongo

    MongoClient 继承了 Mongo。

     1 /**
     2      * Creates a Mongo instance based on a (single) mongo node using a given ServerAddress and default options.
     3      *
     4      * @param addr            the database address
     5      * @param credentialsList the list of credentials used to authenticate all connections
     6      * @param options         default options
     7      * @see com.mongodb.ServerAddress
     8      * @since 2.11.0
     9      */
    10     public MongoClient(final ServerAddress addr, final List<MongoCredential> credentialsList, final MongoClientOptions options) {
    11         super(addr, credentialsList, options);
    12     }

    这个核心构造方法接收三个参数:

    final ServerAddress addr:可以由 new ServerAddress(host, port) 构造。

    final List<MongoCredential> credentialsList: 包含 username, password 等信息。

    final MongoClientOptions options: 包含 MongoDB 数据库的配置信息。

    (5) MongoCredential

    MongoCredential 包含 username, password 等信息。

     1 public final class MongoCredential {
     2 
     3     private final AuthenticationMechanism mechanism;
     4     private final String userName;
     5     private final String source;
     6     private final char[] password;
     7     private final Map<String, Object> mechanismProperties;
     8     
     9     // Other code
    10 }

    三、其他

    Spring-MongoDB 整合与 Spring-MyBatis 相似。

    Spring-MyBatis 的核心类是 SqlSessionTemplate,作用与 MongoTemplate 一样。

  • 相关阅读:
    WCF 第四章 绑定 在多个绑定上暴露一个服务契约
    WCF 第五章 行为 事务跨操作事务流
    WCF 第五章 导出并发布元数据(服务行为)
    WCF 第五章 行为 通过配置文件暴露一个服务行为
    WCF 第五章 不支持会话的绑定的默认并发和实例
    WCF 第五章 并发和实例(服务行为)
    WCF 第五章 行为 总结
    WCF 第四章 绑定 绑定元素
    WCF 第五章 行为 事务之选择一个事务协议OleTx 或者WSAT
    WCF 第四章 绑定 比较各种绑定的性能和可扩展性
  • 原文地址:https://www.cnblogs.com/huangzejun/p/8676934.html
Copyright © 2011-2022 走看看