springboot 整合redis_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 TulingOpenAutoconfigPrincipleApplication {@Autowiredprivate RedisTemplate redisTemplate;public static void main(String[] args) {SpringApplication.run(TulingOpenAutoconfigPrincipleApplication.class, args);}@RequestMapping("/testRedis")public String testRedis() {redisTemplate.opsForValue().set("smlz","smlz");return "OK";}
}
2)综上所述 我们发现,若整合redis的时候通过传统的整合,进行了大量的配置,那么我们来看下通过springboot自动装配整合的对比
导入依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
修改yml配置文件
spring.redis.host=47.104.128.12
spring.redis.port=6379
spring.redis.password=123456
直接使用(下述代码可以不要配置,为了解决保存使用jdk的序列方式才配置的)
@Beanpublic RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<Object, Object> template = new RedisTemplate<>();template.setDefaultSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));template.setConnectionFactory(redisConnectionFactory);return template;}
3)传统整合和springboot自动装配 优劣势分析。。。。。。。。。。。。
4)自动装配原理前的不得不说的几个注解
4.1)通过@Import注解来导入ImportSelector组件
①:写一个配置类在配置类上标注一个@Import的注解,
@Configuration
@Import(value = {TulingSelector.class})
public class TulingConfig {
}
②:在@Import注解的value值 写自己需要导入的组件
在selectImports方法中 就是你需要导入组件的全类名
public class TulingSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {return new String[]{"com.tuling.service.TulingServiceImpl"};}
}
核心代码:
@RestController
public class TulingController {//自动注入 tulingServiceImpl@Autowiredprivate TulingServiceImpl tulingServiceImpl;@RequestMapping("testTuling")public String testTuling() {tulingServiceImpl.testService();return "tulingOk";}
}这里是没有标注其他注解提供给spring包扫描的
public class TulingServiceImpl {public void testService() {System.out.println("我是通过importSelector导入进来的service");}
}
1.2)通过@Import导入ImportBeanDefinitionRegistrar 从而进来导入组件
核心代码:
public class TulingImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {//定义一个BeanDefinitionRootBeanDefinition rootBeanDefinition = new RootBeanDefinition(TulingDao.class);//把自定义的bean定义导入到容器中beanDefinitionRegistry.registerBeanDefinition("tulingDao",rootBeanDefinition);}
}通过ImportSelector功能导入进来的
public class TulingServiceImpl {@Autowiredprivate TulingDao tulingDao;public void testService() {tulingDao.testTulingDao();System.out.println("我是通过importSelector导入进来的service");}
}通过ImportBeanDefinitionRegistar导入进来的
public class TulingDao {public void testTulingDao() {System.out.println("我是通过ImportBeanDefinitionRegistrar导入进来tulingDao组件");}
}
测试结果:
1.3)spring底层条件装配的原理@Conditional
应用要求:比如我有二个组件,一个是TulingLog 一个是TulingAspect
而TulingLog 是依赖TulingAspect的 只有容器中有TulingAspect组件才会加载TulingLog
tulingLog组件 依赖TulingAspect组件
public class TulingLog {
}tulingAspect组件
public class TulingAspect {
}
①:自定义条件组件条件
public class TulingConditional implements Condition {@Overridepublic boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {//容器中包含tulingAspect组件才返回Tureif(conditionContext.getBeanFactory().containsBean("tulingAspect")){return true;}else{return false;}}
}-------------------------------------该情况下会加载二个组件-------------------------------------------------@Beanpublic TulingAspect tulingAspect() {System.out.println("TulingAspect组件自动装配到容器中");return new TulingAspect();}@Bean@Conditional(value = TulingConditional.class)public TulingLog tulingLog() {System.out.println("TulingLog组件自动装配到容器中");return new TulingLog();}-------------------------------------二个组件都不会被加载----------------------------------------/*@Bean**/public TulingAspect tulingAspect() {System.out.println("TulingAspect组件自动装配到容器中");return new TulingAspect();}@Bean@Conditional(value = TulingConditional.class)public TulingLog tulingLog() {System.out.println("TulingLog组件自动装配到容器中");return new TulingLog();}
自动装配原理分析 从@SpringbootApplication入手分析
那我们仔细分析
org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#selectImports
public class AutoConfigurationImportSelectorimplements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,BeanFactoryAware, EnvironmentAware, Ordered {@Overridepublic 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);}}
然后我们分析RedisAutoConfiguration类
导入了三个组件 RedisTemplate StringRedisTemplate JedisConnectionConfiguration
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {//导入redisTemplate @Bean@ConditionalOnMissingBean(name = "redisTemplate")public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {RedisTemplate<Object, Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);return template;}@Bean@ConditionalOnMissingBeanpublic StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {StringRedisTemplate template = new StringRedisTemplate();template.setConnectionFactory(redisConnectionFactory);return template;}}=====================================JedisConnectionConfiguration==========================================@Configuration
@ConditionalOnClass({ GenericObjectPool.class, JedisConnection.class, Jedis.class })
class JedisConnectionConfiguration extends RedisConnectionConfiguration {private final RedisProperties properties;private final List<JedisClientConfigurationBuilderCustomizer> builderCustomizers;JedisConnectionConfiguration(RedisProperties properties,ObjectProvider<RedisSentinelConfiguration> sentinelConfiguration,ObjectProvider<RedisClusterConfiguration> clusterConfiguration,ObjectProvider<List<JedisClientConfigurationBuilderCustomizer>> builderCustomizers) {super(properties, sentinelConfiguration, clusterConfiguration);this.properties = properties;this.builderCustomizers = builderCustomizers.getIfAvailable(Collections::emptyList);}@Bean@ConditionalOnMissingBean(RedisConnectionFactory.class)public JedisConnectionFactory redisConnectionFactory() throws UnknownHostException {return createJedisConnectionFactory();}private JedisConnectionFactory createJedisConnectionFactory() {JedisClientConfiguration clientConfiguration = getJedisClientConfiguration();if (getSentinelConfig() != null) {return new JedisConnectionFactory(getSentinelConfig(), clientConfiguration);}if (getClusterConfiguration() != null) {return new JedisConnectionFactory(getClusterConfiguration(),clientConfiguration);}return new JedisConnectionFactory(getStandaloneConfig(), clientConfiguration);}private JedisClientConfiguration getJedisClientConfiguration() {JedisClientConfigurationBuilder builder = applyProperties(JedisClientConfiguration.builder());RedisProperties.Pool pool = this.properties.getJedis().getPool();if (pool != null) {applyPooling(pool, builder);}if (StringUtils.hasText(this.properties.getUrl())) {customizeConfigurationFromUrl(builder);}customize(builder);return builder.build();}private JedisClientConfigurationBuilder applyProperties(JedisClientConfigurationBuilder builder) {if (this.properties.isSsl()) {builder.useSsl();}if (this.properties.getTimeout() != null) {Duration timeout = this.properties.getTimeout();builder.readTimeout(timeout).connectTimeout(timeout);}return builder;}private void applyPooling(RedisProperties.Pool pool,JedisClientConfiguration.JedisClientConfigurationBuilder builder) {builder.usePooling().poolConfig(jedisPoolConfig(pool));}private JedisPoolConfig jedisPoolConfig(RedisProperties.Pool pool) {JedisPoolConfig config = new JedisPoolConfig();config.setMaxTotal(pool.getMaxActive());config.setMaxIdle(pool.getMaxIdle());config.setMinIdle(pool.getMinIdle());if (pool.getMaxWait() != null) {config.setMaxWaitMillis(pool.getMaxWait().toMillis());}return config;}
}
springboot 整合redis_springboot自动装配原理详解相关推荐
- Spring Boot自动装配原理详解
目录 1.环境和依赖 1.1.spring boot版本 1.2.依赖管理 2.自动装配 2.1.流程概述 2.2.三大步前的准备工作 2.2.1.注解入口 2.2.2.获取所有配置类 2.3.获取过 ...
- 雷神SpringBoot入门和自动装配原理
SpringBoot-helloWord! 首先让当前的工程作为Springboot的子工程 <parent><groupId>org.springframework.boot ...
- SpringBoot--自动装配原理详解及应用之Conditional注解
SpringBoot作为当今开发的主流框架,作为一名java开发是不可能的不了解的,这个东西是典型的用起来很简单,但是了解到原理之后就会不自觉地感叹,真TMNB! 本文主要讲解其自动装配的原理,以及我 ...
- Spring框架中 自动装配的详解 属性值的详解
手动装配实现属性注入 <bean id="studentDao" class="com.xz.dao.impl.StudentDaoImpl">&l ...
- Spring自动装配机制详解
一.什么是自动装配? 自动装配就是会通过Spring的上下文为你找出相应依赖项的类,通俗的说就是Spring会在上下文中自动查找,并自动给Bean装配与其相关的属性! spring中实现自动装配的方式 ...
- 万字长文,图文并茂的给你讲清SpringBoot注解,自动装配原理!
你知道的越多,不知道的就越多,业余的像一棵小草! 你来,我们一起精进!你不来,我和你的竞争对手一起精进! 编辑:业余草 cnblogs.com/jing99/p/11504113.html 推荐:ht ...
- SpringBoot自动装配原理浅析
Springboot自动装配原理 SpringBoot是当下J2EE最为流行的框架,它有着轻量,快捷等特点,让程序员们可以专注在业务逻辑的编写上,而不用花太多的力气在一些环境的配置,整合组件的配置上面 ...
- Spring Boot底层原理详解及整合
Spring Boot框架 通过Spring Boot 可以构建一个基于Spring框架的Java Application,简化配置,自动装配,开箱即用 JavaConfiguration用Java类 ...
- 【SpringBoot】自动装配原理
[SpringBoot]自动装配原理 文章目录 [SpringBoot]自动装配原理 一.pom.xml 1.spring-boot-dependencies 2.spring-boot-starte ...
最新文章
- 聊聊高并发(十六)实现一个简单的可重入锁
- 安卓虚拟机启动后报错: 类似 SDK Manager] Error: Error parsing .....devices.xml 解决方案
- Windows 10 系统版本更新历史
- Linux 下 VuePress 的安装使用
- UOJ #585. 新年和多米诺
- 《软件工艺师:专业、务实、自豪》一2.8 小结
- java中launch方法,Java AppUtils.launchApp方法代码示例
- 解决eclipse中jsp没有代码提示问题
- 微信喊你来找工作:上千家企业将提供超10万个就业岗位
- keil5——常见报错【cannot load flash device description】
- php 异步执行脚本,PHP语言实现脚本异步执行_PHP教程
- dell自带的测试软件,Dell System Detect
- c# 开发ActiveX控件
- 搭建ELK-流水账-只记思路
- PCWorld:流量日趋集中 大公司影响整个互联网
- 香港科大【526清水湾思享会@杭州】暨香港科大EMBA第四届校友会【浙江分会】启动仪式成功举行...
- html时区时间显示,JS显示多个国家时区当前时间代码
- 最新 2022 年云原生Kubernetes 高级面试题大全(持续更新中)
- 【DeepMind】新算法MuZero在Atari基准上取得了新SOTA效果,成果问鼎Nature
- 【C#进阶二】C#中的正则表达式知识总结(字符转义/字符类/ 定位点/ 分组构造 /数量词/反向引用构造/替换构造/替代/正则表达式选项)(理论篇)