• 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 一样。

  • 相关阅读:
    jquery1.9之学习笔记
    ERROR: Removing 'hello': Device or resource busy
    windows虚拟机性能调整
    kvm虚拟机控制台登录配置
    KVM虚拟机的管理
    window kvm 虚拟机的创建
    kvm虚拟化环境的搭建
    C实现哈希表
    哲学家就餐问题 C语言实现
    Linux面试题
  • 原文地址:https://www.cnblogs.com/huangzejun/p/8676934.html
Copyright © 2020-2023  润新知