springboot自动装配原理详解

1)传统ssm整合redis的时候 需要在xml的配置文件中 进行大量的配置Bean

我们在这里使用springboot来代替ssm的整合,通过xml的形式来整合redis

第一步:加入配置

<dependency>
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-redis</artifactId>
	<version>2.0.9.RELEASE</version>
</dependency>

<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>2.9.0</version>
</dependency>

第二步: 配置xml的bean的配置

//配置连接池
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="minIdle" value="10"></property>
        <property name="maxTotal" value="20"></property>
    </bean>
    
    //配置连接工厂
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="47.104.128.12"></property>
        <property name="password" value="123456"></property>
        <property name="database" value="0"></property>
        <property name="poolConfig" ref="poolConfig"></property>
    </bean>


    //配置 redisTemplate 模版类
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory"  ref="jedisConnectionFactory"/>
        <!--如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to String!!  -->
        <property name="keySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <property name="valueSerializer">
            <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
        </property>
        <property name="hashKeySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <property name="hashValueSerializer">
         <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
        </property>
    </bean>

第三步:导入配置

@ImportResource(locations = "classpath:beans.xml")  可以导入xml的配置文件

@SpringBootApplication
@ImportResource(locations = "classpath:beans.xml")
@RestController
public class MossOpenAutoconfigPrincipleApplication {

	@Autowired
	private RedisTemplate redisTemplate;

	public static void main(String[] args) {
		SpringApplication.run(MossOpenAutoconfigPrincipleApplication.class, args);
	}

	@RequestMapping("/testRedis")
	public String testRedis() {
		redisTemplate.opsForValue().set("mossgao","mossgao");
		return "OK";
	}
}

2)综上所述 我们发现,若整合redis的时候通过传统的整合,需要进行大量的配置,那么我们来看下通过springboot自动装配的实现对比

导入依赖

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>

修改application.properties配置文件

spring.redis.host=47.104.128.12
spring.redis.port=6379
spring.redis.password=123456

直接使用(也可以不需要配置stringtemplet, 此处用作java序列化才用到)


	@Bean
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)  {
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setDefaultSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}​

那我们仔细分析

org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#selectImports

 进入源码分析

public class AutoConfigurationImportSelector
		implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
		BeanFactoryAware, EnvironmentAware, Ordered {


	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		//去mata-info/spring.factories文件中 查询 EnableAutoConfiguration对于值
		List<String> configurations = getCandidateConfigurations(annotationMetadata,
				attributes);
		//去除重复的配置类,若我们自己写的starter 可能存主重复的
		configurations = removeDuplicates(configurations);
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);
		//根据maven 导入的启动器过滤出 需要导入的配置类
		configurations = filter(configurations, autoConfigurationMetadata);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return StringUtils.toStringArray(configurations);
	}
}	
 
 //去spring.factories 中去查询EnableAutoConfirution类
 private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
		MultiValueMap<String, String> result = cache.get(classLoader);
		if (result != null) {
			return result;
		}

		try {
			Enumeration<URL> urls = (classLoader != null ?
					classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
					ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
			result = new LinkedMultiValueMap<>();
			while (urls.hasMoreElements()) {
				URL url = urls.nextElement();
				UrlResource resource = new UrlResource(url);
				Properties properties = PropertiesLoaderUtils.loadProperties(resource);
				for (Map.Entry<?, ?> entry : properties.entrySet()) {
					List<String> factoryClassNames = Arrays.asList(
							StringUtils.commaDelimitedListToStringArray((String) entry.getValue()));
					result.addAll((String) entry.getKey(), factoryClassNames);
				}
			}
			cache.put(classLoader, result);
			return result;
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load factories from location [" +
					FACTORIES_RESOURCE_LOCATION + "]", ex);
		}
	}
@Configuration
@ConditionalOnClass({JedisConnection.class, RedisOperations.class, Jedis.class})
@EnableConfigurationProperties({RedisProperties.class})
public class RedisAutoConfiguration {
    public RedisAutoConfiguration() {
    }

    @Configuration
    protected static class RedisConfiguration {
        protected RedisConfiguration() {
        }

        @Bean //如果用户已经创建了redisTemplate,则相关的初始化代码不再执行
        @ConditionalOnMissingBean(
            name = {"redisTemplate"}
        )
        public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
            RedisTemplate<Object, Object> template = new RedisTemplate();
            template.setConnectionFactory(redisConnectionFactory);
            return template;
        }

        @Bean //如果用户已经创建了StringRedisTemplate,则相关的初始化代码不再执行
        @ConditionalOnMissingBean({StringRedisTemplate.class})
        public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
            StringRedisTemplate template = new StringRedisTemplate();
            template.setConnectionFactory(redisConnectionFactory);
            return template;
        }
    }

    @Configuration//动态选择GenericObjectPool
    @ConditionalOnClass({GenericObjectPool.class})
    protected static class RedisConnectionConfiguration {
        private final RedisProperties properties;
        private final RedisSentinelConfiguration sentinelConfiguration;
        private final RedisClusterConfiguration clusterConfiguration;

        public RedisConnectionConfiguration(RedisProperties properties, ObjectProvider<RedisSentinelConfiguration> sentinelConfiguration, ObjectProvider<RedisClusterConfiguration> clusterConfiguration) {
            this.properties = properties;
            this.sentinelConfiguration = (RedisSentinelConfiguration)sentinelConfiguration.getIfAvailable();
            this.clusterConfiguration = (RedisClusterConfiguration)clusterConfiguration.getIfAvailable();
        }

        @Bean
        @ConditionalOnMissingBean({RedisConnectionFactory.class})
        public JedisConnectionFactory redisConnectionFactory() throws UnknownHostException {
            return this.applyProperties(this.createJedisConnectionFactory());
        }

        protected final JedisConnectionFactory applyProperties(JedisConnectionFactory factory) {
            this.configureConnection(factory);
            if (this.properties.isSsl()) {
                factory.setUseSsl(true);
            }

            factory.setDatabase(this.properties.getDatabase());
            if (this.properties.getTimeout() > 0) {
                factory.setTimeout(this.properties.getTimeout());
            }

            return factory;
        }

        private void configureConnection(JedisConnectionFactory factory) {
            if (StringUtils.hasText(this.properties.getUrl())) {
                this.configureConnectionFromUrl(factory);
            } else {
                factory.setHostName(this.properties.getHost());
                factory.setPort(this.properties.getPort());
                if (this.properties.getPassword() != null) {
                    factory.setPassword(this.properties.getPassword());
                }
            }

        }

        private void configureConnectionFromUrl(JedisConnectionFactory factory) {
            String url = this.properties.getUrl();
            if (url.startsWith("rediss://")) {
                factory.setUseSsl(true);
            }

            try {
                URI uri = new URI(url);
                factory.setHostName(uri.getHost());
                factory.setPort(uri.getPort());
                if (uri.getUserInfo() != null) {
                    String password = uri.getUserInfo();
                    int index = password.lastIndexOf(":");
                    if (index >= 0) {
                        password = password.substring(index + 1);
                    }

                    factory.setPassword(password);
                }

            } catch (URISyntaxException var6) {
                throw new IllegalArgumentException("Malformed 'spring.redis.url' " + url, var6);
            }
        }

        protected final RedisSentinelConfiguration getSentinelConfig() {
            if (this.sentinelConfiguration != null) {
                return this.sentinelConfiguration;
            } else {
                Sentinel sentinelProperties = this.properties.getSentinel();
                if (sentinelProperties != null) {
                    RedisSentinelConfiguration config = new RedisSentinelConfiguration();
                    config.master(sentinelProperties.getMaster());
                    config.setSentinels(this.createSentinels(sentinelProperties));
                    return config;
                } else {
                    return null;
                }
            }
        }

        protected final RedisClusterConfiguration getClusterConfiguration() {
            if (this.clusterConfiguration != null) {
                return this.clusterConfiguration;
            } else if (this.properties.getCluster() == null) {
                return null;
            } else {
                Cluster clusterProperties = this.properties.getCluster();
                RedisClusterConfiguration config = new RedisClusterConfiguration(clusterProperties.getNodes());
                if (clusterProperties.getMaxRedirects() != null) {
                    config.setMaxRedirects(clusterProperties.getMaxRedirects());
                }

                return config;
            }
        }

        private List<RedisNode> createSentinels(Sentinel sentinel) {
            List<RedisNode> nodes = new ArrayList();
            String[] var3 = StringUtils.commaDelimitedListToStringArray(sentinel.getNodes());
            int var4 = var3.length;

            for(int var5 = 0; var5 < var4; ++var5) {
                String node = var3[var5];

                try {
                    String[] parts = StringUtils.split(node, ":");
                    Assert.state(parts.length == 2, "Must be defined as 'host:port'");
                    nodes.add(new RedisNode(parts[0], Integer.valueOf(parts[1])));
                } catch (RuntimeException var8) {
                    throw new IllegalStateException("Invalid redis sentinel property '" + node + "'", var8);
                }
            }

            return nodes;
        }

        private JedisConnectionFactory createJedisConnectionFactory() {
            JedisPoolConfig poolConfig = this.properties.getPool() != null ? this.jedisPoolConfig() : new JedisPoolConfig();
            if (this.getSentinelConfig() != null) {
                return new JedisConnectionFactory(this.getSentinelConfig(), poolConfig);
            } else {
                return this.getClusterConfiguration() != null ? new JedisConnectionFactory(this.getClusterConfiguration(), poolConfig) : new JedisConnectionFactory(poolConfig);
            }
        }

        private JedisPoolConfig jedisPoolConfig() {
            JedisPoolConfig config = new JedisPoolConfig();
            Pool props = this.properties.getPool();
            config.setMaxTotal(props.getMaxActive());
            config.setMaxIdle(props.getMaxIdle());
            config.setMinIdle(props.getMinIdle());
            config.setMaxWaitMillis((long)props.getMaxWait());
            return config;
        }
    }
}
发布了22 篇原创文章 · 获赞 10 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/hnhygkx/article/details/88952872