zoukankan      html  css  js  c++  java
  • Spring Boot Mongodb

    Spring注解学习,有助于更好的理解下面代码:

    • @ConditionOnClass表明该@Configuration仅仅在一定条件下才会被加载,这里的条件是Mongo.class位于类路径上
    • @EnableConfigurationProperties将Spring Boot的配置文件(application.properties)中的spring.data.mongodb.*属性映射为MongoProperties并注入到MongoAutoConfiguration中。
    • @ConditionalOnMissingBean说明Spring Boot仅仅在当前上下文中不存在Mongo对象时,才会实例化一个Bean。这个逻辑也体现了Spring Boot的另外一个特性——自定义的Bean优先于框架的默认配置,我们如果显式的在业务代码中定义了一个Mongo对象,那么Spring Boot就不再创建。

    一、先看看spring boot mongo部分源码片段

    /*
     * Copyright 2012-2015 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package org.springframework.boot.autoconfigure.mongo;
    
    import java.net.UnknownHostException;
    
    import javax.annotation.PreDestroy;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.env.Environment;
    
    import com.mongodb.MongoClient;
    import com.mongodb.MongoClientOptions;
    
    /**
     * {@link EnableAutoConfiguration Auto-configuration} for Mongo.
     *
     * @author Dave Syer
     * @author Oliver Gierke
     * @author Phillip Webb
     */
    @Configuration
    @ConditionalOnClass(MongoClient.class)
    @EnableConfigurationProperties(MongoProperties.class)
    @ConditionalOnMissingBean(type = "org.springframework.data.mongodb.MongoDbFactory")
    public class MongoAutoConfiguration {
    
    	@Autowired
    	private MongoProperties properties;
    
    	@Autowired(required = false)
    	private MongoClientOptions options;
    
    	@Autowired
    	private Environment environment;
    
    	private MongoClient mongo;
    
    	@PreDestroy
    	public void close() {
    		if (this.mongo != null) {
    			this.mongo.close();
    		}
    	}
    
    	@Bean
    	@ConditionalOnMissingBean
    	public MongoClient mongo() throws UnknownHostException {
    		this.mongo = this.properties.createMongoClient(this.options, this.environment);
    		return this.mongo;
    	}
    
    }

    /*
     * Copyright 2012-2015 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package org.springframework.boot.autoconfigure.mongo;
    
    import java.net.UnknownHostException;
    import java.util.Collection;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.Set;
    
    import org.springframework.beans.BeanUtils;
    import org.springframework.beans.factory.BeanClassLoaderAware;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.NoSuchBeanDefinitionException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.config.BeanDefinition;
    import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
    import org.springframework.boot.autoconfigure.AutoConfigureAfter;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.env.Environment;
    import org.springframework.core.io.ResourceLoader;
    import org.springframework.core.type.filter.AnnotationTypeFilter;
    import org.springframework.dao.DataAccessException;
    import org.springframework.dao.support.PersistenceExceptionTranslator;
    import org.springframework.data.annotation.Persistent;
    import org.springframework.data.mapping.model.FieldNamingStrategy;
    import org.springframework.data.mongodb.MongoDbFactory;
    import org.springframework.data.mongodb.core.MongoTemplate;
    import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
    import org.springframework.data.mongodb.core.convert.CustomConversions;
    import org.springframework.data.mongodb.core.convert.DbRefResolver;
    import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
    import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
    import org.springframework.data.mongodb.core.convert.MongoConverter;
    import org.springframework.data.mongodb.core.mapping.Document;
    import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
    import org.springframework.data.mongodb.gridfs.GridFsTemplate;
    import org.springframework.util.Assert;
    import org.springframework.util.ClassUtils;
    import org.springframework.util.StringUtils;
    
    import com.mongodb.DB;
    import com.mongodb.Mongo;
    import com.mongodb.MongoClient;
    
    /**
     * {@link EnableAutoConfiguration Auto-configuration} for Spring Data's mongo support.
     * <p>
     * Registers a {@link MongoTemplate} and {@link GridFsTemplate} beans if no other beans of
     * the same type are configured.
     * <P>
     * Honors the {@literal spring.data.mongodb.database} property if set, otherwise connects
     * to the {@literal test} database.
     *
     * @author Dave Syer
     * @author Oliver Gierke
     * @author Josh Long
     * @author Phillip Webb
     * @author Eddú Meléndez
     * @since 1.1.0
     */
    @Configuration
    @ConditionalOnClass({ Mongo.class, MongoTemplate.class })
    @EnableConfigurationProperties(MongoProperties.class)
    @AutoConfigureAfter(MongoAutoConfiguration.class)
    public class MongoDataAutoConfiguration implements BeanClassLoaderAware {
    
    	@Autowired
    	private MongoProperties properties;
    
    	@Autowired
    	private Environment environment;
    
    	@Autowired
    	private ResourceLoader resourceLoader;
    
    	private ClassLoader classLoader;
    
    	@Override
    	public void setBeanClassLoader(ClassLoader classLoader) {
    		this.classLoader = classLoader;
    	}
    
    	@Bean
    	@ConditionalOnMissingBean(MongoDbFactory.class)
    	public SimpleMongoDbFactory mongoDbFactory(MongoClient mongo) throws Exception {
    		String database = this.properties.getMongoClientDatabase();
    		return new SimpleMongoDbFactory(mongo, database);
    	}
    
    	@Bean
    	@ConditionalOnMissingBean
    	public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory,
    			MongoConverter converter) throws UnknownHostException {
    		return new MongoTemplate(mongoDbFactory, converter);
    	}
    
    	@Bean
    	@ConditionalOnMissingBean(MongoConverter.class)
    	public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory,
    			MongoMappingContext context, BeanFactory beanFactory) {
    		DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
    		MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver,
    				context);
    		try {
    			mappingConverter.setCustomConversions(beanFactory
    					.getBean(CustomConversions.class));
    		}
    		catch (NoSuchBeanDefinitionException ex) {
    			// Ignore
    		}
    		return mappingConverter;
    	}
    
    	@Bean
    	@ConditionalOnMissingBean
    	public MongoMappingContext mongoMappingContext(BeanFactory beanFactory)
    			throws ClassNotFoundException {
    		MongoMappingContext context = new MongoMappingContext();
    		context.setInitialEntitySet(getInitialEntitySet(beanFactory));
    		Class<? extends FieldNamingStrategy> strategyClass = this.properties
    				.getFieldNamingStrategy();
    		if (strategyClass != null) {
    			context.setFieldNamingStrategy(BeanUtils.instantiate(strategyClass));
    		}
    		return context;
    	}
    
    	private Set<Class<?>> getInitialEntitySet(BeanFactory beanFactory)
    			throws ClassNotFoundException {
    		Set<Class<?>> entitySet = new HashSet<Class<?>>();
    		ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(
    				false);
    		scanner.setEnvironment(this.environment);
    		scanner.setResourceLoader(this.resourceLoader);
    		scanner.addIncludeFilter(new AnnotationTypeFilter(Document.class));
    		scanner.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
    		for (String basePackage : getMappingBasePackages(beanFactory)) {
    			if (StringUtils.hasText(basePackage)) {
    				for (BeanDefinition candidate : scanner
    						.findCandidateComponents(basePackage)) {
    					entitySet.add(ClassUtils.forName(candidate.getBeanClassName(),
    							this.classLoader));
    				}
    			}
    		}
    		return entitySet;
    	}
    
    	private static Collection<String> getMappingBasePackages(BeanFactory beanFactory) {
    		try {
    			return AutoConfigurationPackages.get(beanFactory);
    		}
    		catch (IllegalStateException ex) {
    			// no auto-configuration package registered yet
    			return Collections.emptyList();
    		}
    	}
    
    	@Bean
    	@ConditionalOnMissingBean
    	public GridFsTemplate gridFsTemplate(MongoDbFactory mongoDbFactory,
    			MongoTemplate mongoTemplate) {
    		return new GridFsTemplate(new GridFsMongoDbFactory(mongoDbFactory,
    				this.properties), mongoTemplate.getConverter());
    	}
    
    	/**
    	 * {@link MongoDbFactory} decorator to respect
    	 * {@link MongoProperties#getGridFsDatabase()} if set.
    	 */
    	private static class GridFsMongoDbFactory implements MongoDbFactory {
    
    		private final MongoDbFactory mongoDbFactory;
    
    		private final MongoProperties properties;
    
    		public GridFsMongoDbFactory(MongoDbFactory mongoDbFactory,
    				MongoProperties properties) {
    			Assert.notNull(mongoDbFactory, "MongoDbFactory must not be null");
    			Assert.notNull(properties, "Properties must not be null");
    			this.mongoDbFactory = mongoDbFactory;
    			this.properties = properties;
    		}
    
    		@Override
    		public DB getDb() throws DataAccessException {
    			String gridFsDatabase = this.properties.getGridFsDatabase();
    			if (StringUtils.hasText(gridFsDatabase)) {
    				return this.mongoDbFactory.getDb(gridFsDatabase);
    			}
    			return this.mongoDbFactory.getDb();
    		}
    
    		@Override
    		public DB getDb(String dbName) throws DataAccessException {
    			return this.mongoDbFactory.getDb(dbName);
    		}
    
    		@Override
    		public PersistenceExceptionTranslator getExceptionTranslator() {
    			return this.mongoDbFactory.getExceptionTranslator();
    		}
    
    	}
    
    }

    /*
     * Copyright 2012-2015 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package org.springframework.boot.autoconfigure.mongo;
    
    import java.net.UnknownHostException;
    import java.util.Arrays;
    import java.util.List;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.core.env.Environment;
    import org.springframework.data.mapping.model.FieldNamingStrategy;
    
    import com.mongodb.MongoClient;
    import com.mongodb.MongoClientOptions;
    import com.mongodb.MongoClientOptions.Builder;
    import com.mongodb.MongoClientURI;
    import com.mongodb.MongoCredential;
    import com.mongodb.ServerAddress;
    
    /**
     * Configuration properties for Mongo.
     *
     * @author Dave Syer
     * @author Phillip Webb
     * @author Josh Long
     * @author Andy Wilkinson
     * @author Eddú Meléndez
     */
    @ConfigurationProperties(prefix = "spring.data.mongodb")
    public class MongoProperties {
    
    	/**
    	 * Default port used when the configured port is {@code null}.
    	 */
    	public static final int DEFAULT_PORT = 27017;
    
    	/**
    	 * Mongo server host.
    	 */
    	private String host;
    
    	/**
    	 * Mongo server port.
    	 */
    	private Integer port = null;
    
    	/**
    	 * Mongo database URI. When set, host and port are ignored.
    	 */
    	private String uri = "mongodb://localhost/test";
    
    	/**
    	 * Database name.
    	 */
    	private String database;
    
    	/**
    	 * Authentication database name.
    	 */
    	private String authenticationDatabase;
    
    	/**
    	 * GridFS database name.
    	 */
    	private String gridFsDatabase;
    
    	/**
    	 * Login user of the mongo server.
    	 */
    	private String username;
    
    	/**
    	 * Login password of the mongo server.
    	 */
    	private char[] password;
    
    	/**
    	 * Fully qualified name of the FieldNamingStrategy to use.
    	 */
    	private Class<? extends FieldNamingStrategy> fieldNamingStrategy;
    
    	public String getHost() {
    		return this.host;
    	}
    
    	public void setHost(String host) {
    		this.host = host;
    	}
    
    	public String getDatabase() {
    		return this.database;
    	}
    
    	public void setDatabase(String database) {
    		this.database = database;
    	}
    
    	public String getAuthenticationDatabase() {
    		return this.authenticationDatabase;
    	}
    
    	public void setAuthenticationDatabase(String authenticationDatabase) {
    		this.authenticationDatabase = authenticationDatabase;
    	}
    
    	public String getUsername() {
    		return this.username;
    	}
    
    	public void setUsername(String username) {
    		this.username = username;
    	}
    
    	public char[] getPassword() {
    		return this.password;
    	}
    
    	public void setPassword(char[] password) {
    		this.password = password;
    	}
    
    	public Class<? extends FieldNamingStrategy> getFieldNamingStrategy() {
    		return this.fieldNamingStrategy;
    	}
    
    	public void setFieldNamingStrategy(
    			Class<? extends FieldNamingStrategy> fieldNamingStrategy) {
    		this.fieldNamingStrategy = fieldNamingStrategy;
    	}
    
    	public void clearPassword() {
    		if (this.password == null) {
    			return;
    		}
    		for (int i = 0; i < this.password.length; i++) {
    			this.password[i] = 0;
    		}
    	}
    
    	public String getUri() {
    		return this.uri;
    	}
    
    	public void setUri(String uri) {
    		this.uri = uri;
    	}
    
    	public Integer getPort() {
    		return this.port;
    	}
    
    	public void setPort(Integer port) {
    		this.port = port;
    	}
    
    	public String getGridFsDatabase() {
    		return this.gridFsDatabase;
    	}
    
    	public void setGridFsDatabase(String gridFsDatabase) {
    		this.gridFsDatabase = gridFsDatabase;
    	}
    
    	public String getMongoClientDatabase() {
    		if (this.database != null) {
    			return this.database;
    		}
    		return new MongoClientURI(this.uri).getDatabase();
    	}
    
    	/**
    	 * Creates a {@link MongoClient} using the given {@code options}
    	 *
    	 * @param options the options
    	 * @return the Mongo client
    	 * @throws UnknownHostException if the configured host is unknown
    	 * @deprecated Since 1.3.0 in favour of
    	 * {@link #createMongoClient(MongoClientOptions, Environment)}
    	 */
    	@Deprecated
    	public MongoClient createMongoClient(MongoClientOptions options)
    			throws UnknownHostException {
    		return this.createMongoClient(options, null);
    	}
    
    	/**
    	 * Creates a {@link MongoClient} using the given {@code options} and
    	 * {@code environment}. If the configured port is zero, the value of the
    	 * {@code local.mongo.port} property retrieved from the {@code environment} is used
    	 * to configure the client.
    	 *
    	 * @param options the options
    	 * @param environment the environment
    	 * @return the Mongo client
    	 * @throws UnknownHostException if the configured host is unknown
    	 */
    	public MongoClient createMongoClient(MongoClientOptions options,
    			Environment environment) throws UnknownHostException {
    		try {
    			if (hasCustomAddress() || hasCustomCredentials()) {
    				if (options == null) {
    					options = MongoClientOptions.builder().build();
    				}
    				List<MongoCredential> credentials = null;
    				if (hasCustomCredentials()) {
    					String database = this.authenticationDatabase == null ? getMongoClientDatabase()
    							: this.authenticationDatabase;
    					credentials = Arrays.asList(MongoCredential.createMongoCRCredential(
    							this.username, database, this.password));
    				}
    				String host = this.host == null ? "localhost" : this.host;
    				int port = determinePort(environment);
    				return new MongoClient(Arrays.asList(new ServerAddress(host, port)),
    						credentials, options);
    			}
    			// The options and credentials are in the URI
    			return new MongoClient(new MongoClientURI(this.uri, builder(options)));
    		}
    		finally {
    			clearPassword();
    		}
    	}
    
    	private boolean hasCustomAddress() {
    		return this.host != null || this.port != null;
    	}
    
    	private boolean hasCustomCredentials() {
    		return this.username != null && this.password != null;
    	}
    
    	private int determinePort(Environment environment) {
    		if (this.port == null) {
    			return DEFAULT_PORT;
    		}
    		if (this.port == 0) {
    			if (environment != null) {
    				String localPort = environment.getProperty("local.mongo.port");
    				if (localPort != null) {
    					return Integer.valueOf(localPort);
    				}
    			}
    			throw new IllegalStateException(
    					"spring.data.mongodb.port=0 and no local mongo port configuration "
    							+ "is available");
    		}
    		return this.port;
    	}
    
    	private Builder builder(MongoClientOptions options) {
    		Builder builder = MongoClientOptions.builder();
    		if (options != null) {
    			builder.alwaysUseMBeans(options.isAlwaysUseMBeans());
    			builder.connectionsPerHost(options.getConnectionsPerHost());
    			builder.connectTimeout(options.getConnectTimeout());
    			builder.cursorFinalizerEnabled(options.isCursorFinalizerEnabled());
    			builder.dbDecoderFactory(options.getDbDecoderFactory());
    			builder.dbEncoderFactory(options.getDbEncoderFactory());
    			builder.description(options.getDescription());
    			builder.maxWaitTime(options.getMaxWaitTime());
    			builder.readPreference(options.getReadPreference());
    			builder.socketFactory(options.getSocketFactory());
    			builder.socketKeepAlive(options.isSocketKeepAlive());
    			builder.socketTimeout(options.getSocketTimeout());
    			builder.threadsAllowedToBlockForConnectionMultiplier(options
    					.getThreadsAllowedToBlockForConnectionMultiplier());
    			builder.writeConcern(options.getWriteConcern());
    		}
    		return builder;
    	}
    
    }
    

    ------------------------------------------------------------------------------------------------------------------------------------------------------

    以上为spring boot mongo的片段,可以看出spring boot已经配置好了,也就是说springboot启动后@Bean创建的对象可以直接使用@Autowrite直接使用

    关注点(spring boot启动会直接读取application.yml或者是application.properties,这里我用的是yml)

    @ConfigurationProperties(prefix = "spring.data.mongodb")
    public class MongoProperties 


    启动入口

    Applicaiton.java 

    package com.modou.weixin;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.mongodb.core.MongoTemplate;
    
    /**
     * Created by chababa on 15/8/22.
     */
    @Configuration
    @ComponentScan(basePackages={"com.modou.conf","com.modou.weixin"})
    @EnableAutoConfiguration
    public class Application implements CommandLineRunner{
    	@Autowired
    	MongoTemplate template;
    	
    	public static void main(String[] args) {
    		SpringApplication.run(Application.class, args);
    	}
    
    	@Override
    	public void run(String... args) throws Exception {
    		System.err.println(template != null);
    	}
    }
    注入MongoTemplate结果


    # SPRING PROFILES
    spring:       
        # HTTP ENCODING
        http:
            encoding.charset: UTF-8
            encoding.enable: true
            encoding.force: true
        data:
            mongodb:
                   host: 127.0.0.1
                   port: 27017
                   username: 
                   password: 
                   database: xx
                   authenticationDatabase:  


  • 相关阅读:
    Java实现 蓝桥杯VIP 基础练习 完美的代价
    Java实现 蓝桥杯VIP基础练习 矩形面积交
    Java实现 蓝桥杯VIP 基础练习 完美的代价
    Java实现 蓝桥杯 蓝桥杯VIP 基础练习 数的读法
    Java实现 蓝桥杯 蓝桥杯VIP 基础练习 数的读法
    Java实现 蓝桥杯 蓝桥杯VIP 基础练习 数的读法
    Java实现 蓝桥杯 蓝桥杯VIP 基础练习 数的读法
    Java实现 蓝桥杯 蓝桥杯VIP 基础练习 数的读法
    核心思想:想清楚自己创业的目的(如果你没有自信提供一种更好的产品或服务,那就别做了,比如IM 电商 搜索)
    在Linux中如何利用backtrace信息解决问题
  • 原文地址:https://www.cnblogs.com/duyinqiang/p/5696533.html
Copyright © 2011-2022 走看看