
spring-boot系列
发布日期:2021-05-07 14:38:26
浏览次数:18
分类:技术文章
本文共 6912 字,大约阅读时间需要 23 分钟。
spring-boot系列
spring-boot自动配置
前言
本节主要讲Condition接口、切换内置服务器、@Enable*注解、@SpringBootApplication四个部分
一、Condition接口
1. 来历
Condition接口,是在spring4.0增加的条件判断功能,可以实现选择性的创建bean操作
2. 使用方法
@Conditional(ClassCondition.class),这个注解需要传递一个实现了Condition接口的class对象,
Condition接口只有一个boolean matches()方法,用此条件来判断这个bean是否创建自定义注解@ConditionOnClass: 首先要继承@Conditional(ClassCondition.class),表明此注解是个衍生注解, 功能和@Conditional()完全一样,但是可以自己定义一个String[] value(); 当其它类使用这个注解时,能够传入String数组,交给自定义的OnClassCondition类 使用,具体写法如下:
@Target({ ElementType.TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documented@Conditional(OnClassCondition.class)public @interface ConditionOnClass { String[] value();}
自定义OnClassCondition: metadata.getAnnotationAttributes(String annotationName).get("value") 方法能获取注解的value数组,这样可以将前面自定义的注解传入并获取 再将每个value进行判断来返回相应的布尔值,就可以实现不同条件是否创建bean本例是通过Class.forName(className);来判断传入的类是否存在,存在就返回true
public class OnClassCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) { String[] classNames = (String[]) metadata.getAnnotationAttributes(ConditionOnClass.class.getName()).get("value"); for (String className : classNames) { try { Class.forName(className); } catch (ClassNotFoundException e) { return false; } } return true; }}
//至此,实现了必须存在这个对象才能创建这个bean @ConditionOnClass("org.springframework.data.redis.core.RedisTemplate") @Bean public RedisTemplate redisTemplate(){ return new RedisTemplate(); }
在Maven:org.springframework.boot:spring-boot-autoconfigure中的condition包下,有一系列的ConditionOn*的注解,就是用来实现各种bean动态创建的,我们通常可以使用这些注解来决定bean是否创建
二、切换内置服务器
1.服务器切换
切换内置服务器jetty、undertow、netty,通过pom文件配置在Maven:org.springframework.boot:spring-boot-autoconfigure中的web包下的embedded包有四个web服务器,修改最后的名字就可以了org.springframework.boot spring-boot-starter-web spring-boot-starter-tomcat org.springframework.boot org.springframework.boot spring-boot-starter-jetty
三、@Enable*注解
1.介绍
@Enable*注解,用于开启某些功能,底层是@import注解,实现bean的动态加载
2.@Import详解
@Import(xxx.class)注解能够将一个类xxx导入spring容器中,通常将其配置spring类上(例如@Configuration),作为导入bean的一种方式,此外,他还有两种方式,一是导入实现了ImportSelector接口的类,通过数组导入: @Import(MyImportSelector.class) 二是导入实现ImportBeanDefinitionRegistrar接口的类,通过bean工厂注册: @Import(MyImportBeanDefinitionRegistrar)以下是实现代码: public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{ "com.lzb.other.bean.User","com.lzb.other.bean.Address"}; } } public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) { AbstractBeanDefinition definition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition(); registry.registerBeanDefinition("com.lzb.other.bean.User",definition); } }@Import()注解底层应该有某种方法,使得一执行这个注解,就会将bean加入到容器中
3.自定义@Enable*类型注解
由于@Import()的功能,我们知道只要引入了这个注解就相当于定义了引入的bean,所以我们只需要写一个衍生注解就可以实现功能:
@Retention(RetentionPolicy.RUNTIME)@Target({ ElementType.TYPE})@Documented@Import(User.class)public @interface EnableUser { }@EnableUser配合getbean或者@Autowired就可以注入
四、@SpringBootApplication
1. @SpringBootApplication启动注解
@SpringBootApplication包括: @SpringBootConfiguration @EnableAutoConfiguration @ComponontScan
2. @SpringBootConfiguration
@Configuration衍生注解,和spring-boot配套使用
@Target({ ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Configurationpublic @interface SpringBootConfiguration { @AliasFor( annotation = Configuration.class ) boolean proxyBeanMethods() default true;}
3.@EnableAutoConfiguration
它是通过@Import导入了AutoConfigurationImportSelector.class,这个类是通过父类实现了ImportSelector接口,并重写了selectImports()方法,来实现bean注入
AutoConfigurationImportSelector类有一个getCandidateConfigurations()方法,这个方法就是用来加载META-INF/spring.factories配置文件,返回可以加载的配置类名的字符串集合,这些字符串就是可加载的类名,进入spring.factories可以发现,他加载了许多类名,但并不是所有的类都会被加载,因为每一个类都有一个@ConditionOn*注解,大多数是@ConditionOnClass(*.class)这个注解用来判定是否加载该类。这个文件十分重要,因为只要启动spring-boot项目,这个文件就会被加载并导入可加载的bean
protected ListgetCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you " + "are using a custom packaging, make sure that file is correct."); return configurations; }
4.@EnableConfigurationProperties(Redis.properties)
原理就是@Enable*,它能够将配置了@ConfigurationProperties(prefix = "redis")的属性文件类导入到容器中,并且优先使用application.yml设置的值
5.自定义starter
这是属性配置类,用来和接收application.yml设置的值,好传递给其它需要的类
package com.lzb.redis.configure;import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix = "redis")public class RedisProperties { private String host = "localhost"; private int port = 6379; public String getHost() { return host; } public void setHost(String host) { this.host = host; } public int getPort() { return port; } public void setPort(int port) { this.port = port; }}
这是提供bean的类,通过@EnableConfigurationProperties(RedisProperties.class)注入配置文件的值,来实现参数的动态化
package com.lzb.redis.configure;import org.springframework.beans.factory.annotation.Autowired;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 redis.clients.jedis.Jedis;@EnableConfigurationProperties(RedisProperties.class)@Configuration@ConditionalOnClass(Jedis.class)public class RedisConfiguration { /** * 提供jedis的bean */ @Bean @ConditionalOnMissingBean(name = "jedis") public Jedis jedis(RedisProperties redisProperties){ return new Jedis(redisProperties.getHost(),redisProperties.getPort()); }}
这是配置文件resources/META-INF/spring.factories 它是随着@EnableAutoConfiguration启动注解加载的,它会先找到这个类,然后对它进行实例化bean的操作,如果满足@ConditionalOnClass(Jedis.class)和@ConditionalOnMissingBean(name = "jedis"),就会将这个bean加入到容器中,否则不创建这个bean ↓
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.lzb.redis.configure.RedisConfiguration
发表评论
最新留言
初次前来,多多关照!
[***.217.46.12]2025年03月19日 20时22分23秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
71 简化路径(模拟、栈)
2019-03-04
892 三维形体的表面积(分析)
2019-03-04
40. 组合总和 II(dfs、set去重)
2019-03-04
16 最接近的三数之和(排序、双指针)
2019-03-04
1333 餐厅过滤器(treemap映射)
2019-03-04
python中的all函数
2019-03-04
1137 第 N 个泰波那契数(迭代、记忆性递归)
2019-03-04
279 完全平方数(dfs)
2019-03-04
279 完全平方数(bfs)
2019-03-04
865 具有所有最深结点的最小子树(递归)
2019-03-04
738 单调递增的数字(找出逆序的位置)
2019-03-04
410 分割数组的最大值(二分查找、动态规划)
2019-03-04
875 爱吃香蕉的珂珂(二分查找)
2019-03-04
693 交替位二进制数(位运算)
2019-03-04
450 删除二叉搜索树中的节点(递归删除节点)
2019-03-04
769 最多能完成排序的块(分析)
2019-03-04
542 01 矩阵(单源bfs、多源bfs)
2019-03-04
1679 K 和数对的最大数目(使用字典对余数分组、排序 + 双指针)
2019-03-04
python测试代码耗时
2019-03-04
蓝桥杯博文链接
2019-03-04