文章目录
- 1 SpringBoot 入门
- 2 应用配置与自动配置
- 2.1类配置与xml配置注解配置
- 2.2启动失败日志
- 2.3自定义失败分析器
- 2.4延迟初始化
- 2.5设置springApplication与流式API
- 2.6事件监听器
- 2.8配置环境后处理器
- 2.10到2.17省略自行查看那篇文章
- 2.18 导入额外的配置文件中出现的注解
- 2.22类型安全的绑定中@ConfigurationProperties注解
- 2.22.4数据校验 JSR303
- 2.23Profile(多环境切换问题)
- 2.25自动配置中注解
- 2.26创建自己的自动配置
- @Configuration: 被修饰的类变成配置类。
- @ConditionalOnClass 当某个类存在时生效
- @ConditionalOnSingleCandidate 上下文中只有一个候选者bean时才注册配置
- @EnableConfigurationProperties 注解的作用是:
- @ConditionalOnMissingBean: 指定bean不在上下文中时,才初始化当前bean
- @AutoCofigureAfter: 指定被修饰的类必须在-个或多个自动配置类加载之后加载。
- @AuoCofijureBefore: 指定被修饰的类必须在一个或名个自动配置类加载之前加载。
- @Import
- **`重点:xxxAutoConfiguration自动配置类注入spring.factorices文件中`**
- @AutoConfigureOrder 指定配置类初始化顺序,越小初始化越早
- **`以下均为重点:springboot里常用条件注解`**
- @ConditionalOnClass、 @ConditionalOMissinglass具体使用
- @ConditionalOnMissingBean、@ConditionalOnBean、@ConditionalOnSingleCandidate具体使用
- @ConditionalOnMissingFilterBean具体使用
- @ConditionalOnProperty使用
- @ConditionalOnResource具体使用
- @ConditionalOnWebAplication、@ConditionalOnNotWebApplication、@ConditionalOnWarDeployment 使用
- @ConditionalOnExpression使用
- @ConditionalOnCloudPlatfom @ConditioalOnJava、@ConditionalOnJndi、@ConditionalOnRepositoryType使用
- 3 springboot的web应用支持
一定要看
1 SpringBoot 入门
@Controller
用于修饰类 指定该类的实例作为控制组件
@GetMapping
用于修饰方法和类,指定该方法所能处理Get请求的地址
@ResponseBody
用于修饰方法和类, 支持将返回值放到response内,而不是一个页面,通常用户返回json数据。
@springBootAppliction注解相当于以下3个注解的组合版
@Configuration
该注解修饰的类作为java配置类
@EnableAutoConfiguration
启动自动配置
@ComponentScan
指定“零配置”时扫描哪些包及其以下包的bean
2 应用配置与自动配置
2.1类配置与xml配置注解配置
@Component:
泛指各种组件
@Controller、@Service、@Repository
本质就是@Component
@Controller:控制层
@Service:业务层
@Repository:数据访问层
@Import
该注解显示指定springboot要加载的配置类
/**
加载org.app和com.app包下的TestA和Teast文件作为配置类
**/
@Import({org.app.TestA.class,com.app.Teast.class})
@ImportResource(“classpath:beans.xml”)
加载类加载路径下beans.xml文件作为配置文件
@ComponentScan
该注解指定springboot扫描指定包及其子包下的所有配置类或者bean组件
@SpringBootApplication(scanBasePackages = {})
其scanBasePackages属性本质就是@ComponentScan注解中basePackages属性
// 额外指定扫描org.app和com.app包及其包下的配置类和Bean组件
@SpringBootApplication(scanBasePackages = {"org.app","com.app"})
2.2启动失败日志
如果没有合适的失败分析器来处理启动过程中出现的错误,但依然希望SpringBoot显示完整的错误报告,则可通过开启debug 属性,或者将ConditionEvaluationReportL oggingListener的日志级别设为DEBUG来实现。
在application.properties文件中添加如下配置,可以将ConditionEvaluationReportL oggingListener的日志级别设为DEBUG。
logging.level.org.springframework.boot.autoconfigure.logging=debug
2.3自定义失败分析器
开发者自定义失败分析器,需要继承 AbstractFailureAnalyzer<T>
该泛型T代表失败分析器要处理的异常 继承这个类就必须实现analyze()方法该方法,返回FailureAnalysis对象代表该异常的分析结果。如果不想让该失败分析器分析该异常,而是希望将该异常留给下一个分析器进行分析,则可让该方法返回null
public FailureAnalysis(String description, String action, Throwable cause) {
this.description = description;
this.action = action;
this.cause = cause;
}
description 失败的描述信息
action 对该失败的修复建议
cause 导致失败的异常
实列
public class MyAnalyzer extends AbstractFailureAnalyzer<BindException>
{
@Override
public FailureAnalysis analyze(Throwable rootFailure, BindException cause)
{
cause.printStackTrace();
return new FailureAnalysis("程序启动出错,程序绑定的端口被占用:"
+ cause.getMessage(),
"请先停止占用8080端口的程序后再运行本应用或使用" +
"server.port改变本应用的端口", cause);
}
}
自定义失败分析器需要在META-INF/spring.factories文件中注册,首先需要在resources目录下创建META-INF文件夹,然后在META-INF文件夹创建spring.factories文件里面内容为
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.crazyit.app.MyAnalyzer
2.4延迟初始化
在某些特殊需求下,Spring Boo也允许将取消Application Context的预初始化行为改为延迟初始化。要将Spring容器设为延迟初始化,有如下三种方式。
➢调用SpringApplication对象的setlazylnitialization(true)方法。
需要在启动类中配置如
@SpringBootApplication
public class App
{
public static void main(String[] args)
{
// 创建Spring容器、运行Spring Boot应用
var application=new SpringApplication(App.class);
// 设置启用延迟初始化
application.setLazyInitialization(true);
application.run(args);
}
}
➢调用SpringApplicationBuilder对象的lazyInitialization(true)方法。
@SpringBootApplication
public class App
{
public static void main(String[] args)
{
new SpringApplicationBuilder().
//加载父容器对应的配置类
sources(Parent.class).
//App类对应的配置作为子容器
child(App.class).
//启用延迟初始化
lazyInitialization(true).
//关闭Banner
bannerMode(Banner.Mode.OFF).run(args);
}
}
➢在application.properties文件中配置如下代码:
spring.main.lazy-initialization=true
2.5设置springApplication与流式API
要对SpringApplication进行自定义设置,比如之前调用setLazyInitialization()方法启用延迟初始化,调用setBanner()方法设置Banner等
@SpringBootApplication
public class App
{
public static void main(String[] args)
{
// 创建Spring容器、运行Spring Boot应用
var application=new SpringApplication(App.class);
// 设置启用延迟初始化
application.setLazyInitialization(true);
Banner banner=.......;
// 设置banner
application.setgBanner(banner);
application.run(args);
}
}
除了直接调用构造器来创建SpringApplication对象,Spring Boot还提供了SpringplicationBuilder工具类,通过该工具类能以流式API创建SpringApplication,并启动Spring Boot应用。
此外,SpringApplicationBuilder 还提供了如下方法来加载配置文件。
➢sources(Class<?>… sources):为应用添加配置类。
➢child(Class<?>… sources): 为当前容器添加子容器配置类。
➢parent(Class<?>… sources):为当前容器添加父容器配置类。
从这些方法可以看出,使用SpringApplicationBuilder可以构建ApplicationContext的层次结构(让Spring容器具有父子关系)。例如,如下代码片段使用SpringApplicationBuilder来启动SpringBoot应用。
@SpringBootApplication
public class App
{
public static void main(String[] args)
{
new SpringApplicationBuilder().
//加载父容器对应的配置类
sources(Parent.class).
//App类对应的配置作为子容器
child(App.class).
//启用延迟初始化
lazyInitialization(true).
//关闭Banner
bannerMode(Banner.Mode.OFF).run(args);
}
}
2.6事件监听器
为了监听SpringApplication触发的事件,SpringAplication提供了如下方式来注册事件监听器。
➢调用 SpringApplication的addLiseners()方法或SpringApplicationBuider的listners()方法添加事件监听器。
➢使用META-INF/spring. factories 文件来配置事件监听器。在该文件中添加如下代码即可始册事件监听器:
# 定义事件监听器
org.springframework.context.ApplicationListener=\
org.crazyit.app.MyListener
如果应用程序采用了层次结构的容器(通过SpringAplicationBuilder启动Spring Boot应用时,可使用层次结构的容器), 那么事件监听器就有可能接收到同一类型事件的多个实例一它 们来自不同的容器。
为了让事件监听器能区分事件到底来自哪个容器,可以用事件监听器依赖注入的容器与事件来自的容器进行比较;为了将容器依赖注入事件监听器,可通过如下两种方式。
接口注入:让事件监听器实现ApplicationContextAware 接口,Spring容器将会被注入监听器。
➢普通注入:如果事件监听器是容器中的Bean, 则可直接使用@Autowired注解来完成依赖注入。
2.7容器初始化
除了监听器,Spring Boot还提供了ApplicationContextInitializer 对Spring容器执行初始化。
ApplicationContextInitializer接口的实现类被称为“初始化器”,该接口的实现类必然实现其中的
initialize(C ctx)方法,通过该方法的参数也可对Spring容器进行设置。
有了ApplicationContextInitializer实现类之后,接下来可通过如下方式来注册初始化器。
➢调用SpringApplication 的addInitializers(方法或SpringApplicationBuilder的initializers()方法添加初始化器。
➢使用META-INF/spring. factories 文件来配置初始化器。在该文件中添加如下代码即可注册初始化器:
# 定义初始化器
org.springframework.context.ApplicationContextInitializer=\
org.crazyit.app.MyInitializer
2.8配置环境后处理器
如果想在Eavironment对象创建之后、Spring 容器刷新之前对Enironment对象(配置环境)进行定制,Spring Boot提供了配置环境后处理器一实现 EnironmentPostProcessor接口的类被称为“配置环境后处理器”。EnvironmentPostProcessor 实现类必然实现其中的postProcessEnvironmem(enviroment,application)方法,通过该方法的参数可对创建Spring容器的Environment进行额外的定制,比如将自定义的配置文件的属性加载到配置环境中。
注意:
可能有人会产生疑问:直接在Spring Boot配置类(用@SpringBootApplication修饰的类)中用@ValueSource注解加载自定义资源,然后将它添加到Environment中,这样不是更方便吗?请记住一点: @ValueSource 注解必须等到Spring容器刷新之后才会得到处理,此时去读取@ValueSource注解所加载的资源,再添加到Environment中已经太迟了。
有了ApplicationContextInitializer 实现类之后,可通过META-INF/spring. fctories文件来注册配置环境后处理器。例如如下代码:
# 定义配置环境后处理器
org.springframework.boot.env.EnvironmentPostProcessor=\
org.crazyit.app.FkEnvironmentPostProcessor
2.9监听器、初始化器、配置环境后处理器实例
2.10到2.17省略自行查看那篇文章
2.18 导入额外的配置文件中出现的注解
@PropertySource 导入引入properties文件:
@PropertySource(value = {"classpath:xxxx/xxxx.properties","classpath:xxxx/xxxx.properties"})
主类中使用@PropertySource注解导入crazyit.prpertis文件
@PropertySource("classpath:/fk/crazyit.properties")
spring.config.import属性导入额外的yaml和properties配置文件。
yml 文件只能通过spring.config.import属性导入无法使用@PropertySource注解导入
spring:
config:
# 指定导入类加载路径下fk/fk.yml文件
import: optional:classpath:/fk/fk.yml
其中optional:classpath:/fk/使用了optional:前缀,用于告诉Spring Boot不要检查该路径下是否
存在配置文件,如果该路径下存在配置文件就加载,否则就忽略该路径。如果不添加optional:前缀,那么Spring Boot会强制检查该路径下是否存在配里文件:若该路径下不存在任何配置文件,则
Spring Boot将会抛出ConfigDataLocationNotFoundException异常。
2.22类型安全的绑定中@ConfigurationProperties注解
读取配置文件的属性
使用@Value注解来读取配置文件中的属性,但使用@Value注解每次只能读取
一个配置属性,若需要整体读取多个属性,或者读取具有某种结构关系的一组属性,Spring Boot
则提供了==@ConfigurationProperties==注解来进行处理。
@ConfigurationProperties注解有两种主要用法。
➢修饰属性处理类:当@ConfigurationProperties 注解修饰的类被部署为容器中的Bean时,该注解指定的属性将会被注入该Bean的属性。因此,将@ConfigurationProperties在解珍饰的
类称为“属性处理类”。
➢修饰@Bean 注解修饰的方法:使用@Bean修饰的方法将会配置一个容器中的Bean, 而@ConfigurationProperties注解指定的属性将会被注入该Bean的属性。
在使用@ConfigurationProperties注解时可指定如下属性。
➢prefix(或value):指定要加载的属性的前缀。
➢ignoreInvalidFields(): 指定是否忽略无效属性值。比如处理类定义了某个字段的类型是
Integer,但在配置文件中为该字段配置的值是abc,这就是无效的值。
➢ignoreUnknownFields():指定是否忽略未知的字段值。如果在配置文件中配置的属性比处
理类需要的属性更多,那么多出来的属性就属于未知属性。
org.crazyit.item.brand=Tesla
org.crazyit.item.comments=Good, Excellent
//读取配置中org.crazyit开头的属性
@ConfigurationProperties(prefix = "org.crazyit", ignoreUnknownFields=false)
Spring Boot并不会自动启用@ConfigurationProperties注解。让Spring Boot启
用该注解有如下方式:
1 ➢为@ConfigurationProperties 注解修饰的类添加@Component注解。
2 ➢将@ConfigurationProperties 注解修饰的类显式配置成容器中的Bean。
3 ➢使用@EnableConfigurationProperties 注解,该注解可显式指定一个或多个属性处理类,
Spring Boot将会启用这些属性处理类上的@ConfigurationProperties注解。
4 ➢使用@ConfigurationPropertiesScan 注解,该注解可指定启用一个或多个包及其子包下所有
带@ConfigurationProperties注解的类。
@EnableConfigurationProperties注解
使用@EnableConfigurationProperties注解,该注解可显式指定一个或多个属性处理类,
Spring Boot将会启用这些属性处理类上的@ConfigurationProperties注解。
@ConstructorBinding 构造器属性注入
实际上,属性处理类同样也支持用构造器来完成属性值注入,只要额外使用@ConstructorBinding
注解修饰用于执行属性值注入的构造器即可。如果该类仅包含一个构造器,则可直接用该注解修饰
属性处理类。
值得注意的是,如果使用构造器来完成属性值注入,则要求使用@EnableConfigurationProperties
注解或@ConfigurationPopriesScan注解来启用@ConfiguratioProperties注解。
@ConfigurationProperties(prefix = "org.crazyit", ignoreUnknownFields=false)
public class CrazyitProperties
{
private boolean enabled;
private String name;
private InetAddress remoteAddress;
private final Item item;
**@ConstructorBinding**
public CrazyitProperties(boolean enabled, String name, InetAddress remoteAddress, Item item)
{
this.enabled = enabled;
this.name = name;
this.remoteAddress = remoteAddress;
this.item = item;
}
public boolean isEnabled()
{
return this.enabled;
}
public String getName()
{
return name;
}
public InetAddress getRemoteAddress()
{
return remoteAddress;
}
public Item getItem()
{
return item;
}
public static class Item
{
private String brand;
private List<String> comments = new ArrayList<>(Collections.singleton("GREAT"));
public String getBrand()
{
return brand;
}
public void setBrand(String brand)
{
this.brand = brand;
}
public List<String> getComments()
{
return comments;
}
public void setComments(List<String> comments)
{
this.comments = comments;
}
}
}
面的属性处理类并未为实例变量定义setter方法,而是定义了一个带参数的构造器,且该构造器使用了@ConstructorBinding修饰,这样Spring Boot将会使用构造器来完成属性值注入。下面是本例的配置文件,该配置使用了YAML格式(本质是一样的)。
org:
crazyit:
enabled: true
name: 疯狂Java
remote-address: 192.168.1.188
item:
brand: Apple
comments:
- Good
- Excellent
对于用构造器执行属性值注入的属性处理类,要求使用@ConfigurationPropertiesScan或
@EnableConfigurationProperties注解来启用@ConfigurationProperties,因此本例在应用主类上增加
了@ConfigurationPropertiesScan注解。下面是本例的应用主类。
@SpringBootApplication
// 指定扫描org.crazyit.app.config包及其子包下的@ConfigurationProperties注解修饰的类
**@ConfigurationPropertiesScan("org.crazyit.app.config")**
public class App
{
public static void main(String[] args)
{
// 创建Spring容器、运行Spring Boot应用
SpringApplication.run(App.class, args);
}
}
2.22.4数据校验 JSR303
注解自行查看
2.23Profile(多环境切换问题)
@Profile
使用@Profle 注解修饰@Component、@Configuration、 @ConfigurationProperties 等注解修
饰的类,这限制了这些类仅对特定的Profile有效。
指定Bean在哪个环境下被激活
如
@RestController
@Profile("default")
public class DefaultController
{
}
2.25自动配置中注解
@ConditionalOnMissingBean
指定只有当容器中不存在指定类型的Bean时,@Bean注解所配置的Bean才会生效。
如
@ConditionalOnMissingBean({DataSource.class})
@Bean
public DataSource dataSource (){
return new XxxDataSource();
}
上面配置指定只有当容器中不存在类型为DataSource的Bean时,@Bean注解所配置的Bean
才会生效。
再比如
@ConditionalOnMissingBean(name = "dataSource")
@Bean
public DataSource dataSource (){
return new XxxDataSource ();
}
上面配置指定只要容器中不存在ID为dataSource的Bean,@Bean注解所配置的Bean就会
生效。
2.25.1 禁用特定的自动配置 @EnableAutoConfiguration注解
通过@EnableAutoConfiguration注解的如下属性来指定。
➢exclude: 该属性的值可以是一个Class 数组,用于禁用一个或多 个自动配置类。
➢excludeName:与前一个属性的作用基本相同,只不过它指定一个或者多个自动配置类的完整类名的字符串形式。
而在实际项目中通常使用@SpringBootApplication注解,该注解己包含了@EnableAutoConfiguration
注解,@SpringBootApplication 注解的exclude和excludeName属性就是@EnableAutoConfiguration
注解的这两个属性的别名。
@ConditionalOnMissingBean(name = "dataSource")
@Bean
public DataSource dataSource (){
return new XxxDataSource ();
}
上面配置指定只要容器中不存在ID为dataSource的Bean,@Bean注解所配置的Bean就会
生效。
由于Spring Boot的自动配置具有一定的透明性(有时候无法准确地知道Spring Boot自动配置了哪些Bean),因此Spring Boot为应用程序提供了“--debug
"开关。
如果通过“--debug
”开关启动SpringBoot应用,则将为核心组件开启DEBUG级别的图志,
并将自动配置的相关日志输出到控制台。
2.25.2禁用特定的自动配置
在某些情况下,如果希望应用禁用特定的自动配置类,则可通过@EnableAutoConfiguration注
解的如下属性来指定。
➢exclude: 该属性的值可以是一个Class 数组,用于禁用一个或多 个自动配置类。
➢excludeName:与前一个属性的作用基本相同,只不过它指定一个或者多个自动配置类的完整类名的字符串形式。
而在实际项目中通常使用@SpringBootApplication注解,该注解己包含了@EnableAutoConfiguration
注解,@SpringBootApplication 注解的exclude和excludeName属性就是@EnableAutoConfiguration
注解的这两个属性的别名。
例如,如下主类上的@SpringBootApplication注解可禁用DataSourceAutoConfiguration自动配
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class App
{
public static void main(String[] args)
{
// 创建Spring容器、运行Spring Boot应用
SpringApplication.run(App.class, args);
}
}
上面粗体字代码使用exclude属性指定了要禁用的自动配置类,如果使用excludeName属性,
则务必指定要禁用的自动配置类的全限定类名。
此外,Spring Boot也允许在application.propertes文件中通过spring autoconfigure exclude属性
来指定要禁用的自动配置类。例如如下配置:
spring. autoconfigure. exclude=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
上面的配置片段表示禁用了DataSourceAutoConfiguration、 Redis AutoConfiguration两个自动配
置类。
2.26创建自己的自动配置
@Configuration: 被修饰的类变成配置类。
@ConditionalOnClass 当某个类存在时生效
@ConditionalOnSingleCandidate 上下文中只有一个候选者bean时才注册配置
@EnableConfigurationProperties 注解的作用是:
让使用了 @ConfigurationProperties 注解的类生效,并且将该类注入到 IOC 容器中,交由 IOC 容器进行管理
@ConditionalOnMissingBean: 指定bean不在上下文中时,才初始化当前bean
@AutoCofigureAfter: 指定被修饰的类必须在-个或多个自动配置类加载之后加载。
@AuoCofijureBefore: 指定被修饰的类必须在一个或名个自动配置类加载之前加载。
@Import
该注解显示指定springboot要加载的配置类
重点:xxxAutoConfiguration自动配置类注入spring.factorices文件中
自动配置类只能通过META-INF/spring factories进行加载,并确保它们处于一个特殊的包空间内,尤其是不能让它们变成普通@ComponentScan的目标。此外,自动配置类也不应该用@ComponentScan来扫描其他组件,如果确实需要加载其他配置文件,则应使用@Import显式指定重要加载的配置类。
如果要为自动配置类指定它们的加载顺序,Spring Boot则提供了如下两个注解。
@AutoCofigureAfter: 指定被修饰的类必须在-个或多个自动配置类加载之后加载。
@AuoCofijureBefore: 指定被修饰的类必须在一个或名个自动配置类加载之前加载。
@AutoConfigureOrder 指定配置类初始化顺序,越小初始化越早
=========================================================================
以下均为重点:springboot里常用条件注解
➢类条件注解: @ConditionalOnClass、 @ConditionalOMissinglass
如何具体使用
➢Bean条件注解: @ConditionalOnMissingBean、CndionalOningleCandidate、@ConditionalOnBean、@ConditionalOnMissingFilterBean.
如何具体使用
如何具体使用@ConditionalOnMissingFilterBean
➢
属性条件注解: @ConditionalOnProperty。
如何具体使用
➢资源条件注解: @ConditionalOnResource。
如何具体使用
➢Web 应用条件注解: @ConditionalOnWebAplication、@ConditionalOnNotWebApplication.
@ConditionalOnW arDeployment。 如何具体使用
➢SpEL 表达式条件注解: @ConditionalOnExpression
. 如何具体使用
➢特殊条件注解: @ConditionalOnCloudPlatfom @ConditioalOnJava、@ConditionalOnJndi
@ConditionalOnRepositoryType。 如何具体使用
上面这些条件注解都是基于Spring的@Conditional条件注解
变化而来的。
=========================================================================
@ConditionalOnClass、 @ConditionalOMissinglass具体使用
@ConditionalOnClass、 @ConditionalOMissinglass具体使用
类条件注解有两个,即CondialonClass 和 @ConditionalOMissinglass,分别表示某些类存在或者不存在时被修饰的类或被修饰的方法生效。@ConditionalOnClass 注解可通过value或name属性
指定它所要求存在的类,其中value属性值是被检查类的Class对象,name 属性值是被检查类的字符串形式的全限定类名,既然是检查目 标类是否存在,那么通常用name属性值居多
;
@ConditionalOnMissingClass则只能通过value属性指定它所要求不存在的类,value 属性值只能是
被检查类的字符串形式的全限定类名,既然要确保该类不存在,那么该类对应的Class通常也就
不存在了。
@ConditionalOnMisingClass注解的用法与@ConditionalOnClass注解的用法大致相同,只不过
它要求的是被检查类不存在,这样被它修饰的配置类或方法才会生效。
=========================================================================
@ConditionalOnMissingBean、@ConditionalOnBean、@ConditionalOnSingleCandidate具体使用
@ConditionalOnMissingBean、@ConditionalOnBean、 @ConditionalOnSingleCandidate
@ConditionalOnMissingBean、@ConditionalOnBean、 @ConditionalOnSingleCandidate 都用于要
求目标Bean存在或不存在(带Missing的注解要求目标Bean不存在)。它们大致可指定如下属性。
➢Class<? extends Annotation>[] annotation:指定要检查的Bean必须用该属性指定的注解修饰。
➢Class<?>[] ignored: 指定忽略哪些类型的Bean。 该属性及ignoredType 属性仅对@ConditionalOnMissingBean注解有效
。
➢String[] ignoredType:与ignored属性的作用相同,只不过该属性用字符串形式的全限定类名
。
➢String[] name: 指定要检查的Bean的ID
.
➢search:指定搜索目标Bean的搜索策略, 支持CURRENT(仅在容器中搜索)、ANCESTORS(仅在祖先容器中搜索)、ALL (在所有容器中搜索)三个枚举值
。
➢Class<?>[] value: 指定要检查的Bean的类型
。
➢String[] type: 与value属性的作用相同,只不过该属性用字符串形式的全限定类名
。
@ConditionalOnSingleCandidate注解相当于@ConditionalOnBean的增强版,它不仅要求被检查的Bean必须存在
,而且只能有一个“候选者”
,能满足byType依赖注入的条件。从上面的属性可以看出,如果指定value 或type 属性,则意味着@ConditionalOnBean、的Bean必须存在,而且只能有一个“候选者”一能满足 byType依赖注入的条件。
从上面的属性可以看出,如果指定value 或type 属性,则意味着@ConditionalOnBean、
@ConditionalOnMissingBean注解将根据目标Bean的类型进行检查(即要求特定类型的Bean必须存在或不存在);如果指定name属性,则意味着@ConditionalOnBean、@ConditionalOnMissingBean注解将根据目标Bean的ID进行检查(即要求特定ID的Bean必须存在或不存在);
如果指定annotation属性,则意味着@ConditionalOnBean、@ConditionalOnMissingBean注解将根据目标Bean所带的注解进行检查(即要求带特定注解的Bean必须存在或不存在)。
**如果@ConditionalOnBean、@ConditionalOnMissingBean 注解不指定任何属性,则默认根据目标Bean的类型进行检查,默认检查被修饰的方法所返回的Bean类型**
=========================================================================
@ConditionalOnMissingFilterBean具体使用
@ConditionalOnMissingFilterBean
@ConditionalOnMissingFilterBean注解相当于@ConditionalOnMissingBean的特殊版本,它专门用于检查容器中是否存在指定类型的javax.servlet.Filter
,因此它只能通过value属性指定其要检查的Filter的类型。
=========================================================================
@ConditionalOnProperty使用
@ConditionalOnProperty
@ConditionalOnProperty注解用于检查特定属性是否具有指定的属性值。
该注解支持如下属性。
String[]value;指定要检查的属性。
➢String[] name:指定value属性的别名
。
String havingValue:指定被检查属性必须具有的属性值
。
String prefix:自动为各属性名添加该属性指定的前缀
。
➢boolean matchIfMissing: 指定当属性未设置属性值时,是否通过检查
。
havingValue属性用于指定被检查属性必须具有的属性值,该属性值共有三种 true,false,foo
@Configuration(proxyBeanMethods = false)
public class FkConfig
{
@Bean
// 只有当org.fkjava.test属性具有foo属性值时,下面配置方法才会生效
@ConditionalOnProperty(name = "test", havingValue = "foo",
prefix = "org.fkjava")
public DateFormat dateFormat()
{
return DateFormat.getDateInstance();
}
}
上面粗体字注 解指定了name = "test"和 prefix = “org.fkjava”, 表明该注解要检查org. fkjava.test配置属性,且要求其属性值为foo (由havingValue属性指定)。
在application.properties文件中添加如下配置:
org.fkjava.teste=foo
@ConditionalOnProperty(name = “test”, havingValue = “foo”,prefix = “org.fkjava”)
总结下来就是 在配置文件中前缀为 “org.fkjava”,属性为"test", 属性值为"foo"
=========================================================================
@ConditionalOnResource具体使用
@ConditionalOnResource注解的作用很简单,它要求指定的资源必须存在,其修饰的配置类或
方法才会生效
。使用该注解时只需指定resourees属性,该属性指定必须存在的资源。
=========================================================================
@ConditionalOnWebAplication、@ConditionalOnNotWebApplication、@ConditionalOnWarDeployment 使用
@ConditionalOnWebAplication、@ConditionalOnNotWebApplication.
@ConditionalOnWarDeployment
@ConditionalOnWebApplication要求当前应用必须是Web应用时
,其修饰的配置类或方法才会
生效。使用该注解时可通过type属性指定Web应用的类型,该属性支持如下三个枚举值。
➢
ANY:当前应用是任何Web应用时,该注解修饰的配置类或方法都会生效
。
➢
REACTIVE: 只有当应用是反应式Web应用时(Spring WcbFlux),该注解修饰的配置类或方法才会生效
。
➢SERVLET: 只有当应用是基于Servlet的Web应用时(Spring MVC),该注解修饰的配置类或方法才会生效
。
@ConditionalOnNotWebApplication则要求当前应用不是Web应用时
,该注解修饰的配置类或方法才会生效。
@ConditionalOnWarDeployment要求当前应用以传统WAR包方式被部署到Web服务器或应用服务器中时(不以独立Java程序的方式运行),该注解修饰的配置类或方法才会生效。
@ConditionalOnNotWebApplication和@ConditionalOnWarDeployment用起来更简单,它们都不
需要指定任何属性。
配置反应式web
配置类如下
@Configuration(proxyBeanMethods = false)
public class FkConfig
{
@Bean
// 只有当前应用是反应式Web应用时,该配置才会生效
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public DateFormat dateFormat()
{
return DateFormat.getDateInstance();
}
}
上面的粗体字注解要求当前应用是反应式Web应用,只有这样该注解修饰的方法才会生效,由于项目中同时添加了Spring WebFlux依赖和Sping Web依赖,因此该应用既可以是基于Servlet的Web应用,也可以是反应式Web应用,具体取决于SpingAplication的设置
下面是本例的启动类代码。
@SpringBootApplication
public class App
{
public static void main(String[] args)
{
var app = new SpringApplication(App.class);
// 设置Web应用的类型,如果不设置则使用默认的类型:
// 如果有Sping Web依赖,自动是基于Servlet的Web应用
// 如果有Sping WebFlux依赖,自动是反应式Web应用
app.setWebApplicationType(WebApplicationType.REACTIVE); // 1
// 创建Spring容器、运行Spring Boot应用
var ctx = app.run(args);
System.out.println(ctx.getBean("dateFormat"));
}
}
=========================================================================
@ConditionalOnExpression使用
@ConditionalOnExpression注解要求指定SpEL表达式的值为true,这样其所修饰的配置类或方法才会生效。
例如下面的配置类。
@Configuration(proxyBeanMethods = false)
public class FkConfig
{
@Bean
public User user()
{
return new User("fkjava", true);
}
@Bean
// 只有当user.active表达式为true时,该方法才生效
*******@ConditionalOnExpression("user.active")*****
public DateFormat dateFormat()
{
return DateFormat.getDateInstance();
}
}
public class User
{
private String name;
private boolean active;
public User(String name, boolean active)
{
this.name = name;
this.active = active;
}
}
主启动类和上面不变
上面的粗体字注解要求user.active 表达式为true时,其修饰的方法才会生效。此处的user activev就是一个SpEL表达式,它负责解析容器中user 的active属性。由于在该配置类前面还配置了一个user Bean,
且该user的active属性为true,因此上面的dateFormat()方法会生效。
=========================================================================
@ConditionalOnCloudPlatfom @ConditioalOnJava、@ConditionalOnJndi、@ConditionalOnRepositoryType使用
@ConditionalOnCloudPlatfom @ConditioalOnJava、@ConditionalOnJndi.
@ConditionalOnRepositoryType
@ConditionalOnCloudPlatform注解要求应用被部署在特定云平台上
,这样其修饰的配置类或
方法才会生效。该注解可通过value属性指定它所要求的云平台,该value属性支持如下枚举值。
➢CLOUD FOUNDRY: 要求应用被部署在CLOUD_FOUNDRY云平台上时,该注解修饰的配置类或方法才会生效
。
➢HEROKU:要求应用被部署在HEROKU平台上时,该注解修饰的配置类或方法才会生效。
➢KUBERNETES: 要求应用被部署在K8s平台上时,该注解修饰的配置类或方法才会生效。
➢SAP:要求应用被部署在SAP云平台上时,该注解修饰的配置类或方法才会生效。
@CndtioalOnlava注解对目标平台的Java 版本进行检测
,它既可要求目标平台的Java 版本是某个具体的版本, 也可要求其高于或低于某个版本。使用该注解时可指定如下两个属性。
➢JavaVersion value:指定要求的Java版本。
➢ConditionalOnJava.Range range:该属性支持EQUAL_OR_NEWER (大于或等于value属性指定的版本)和OLDER_THAN (小于value 属性指定的版本)两个枚举值。如果不指定该属性,则要求目标平台的Java版本必须是value属性所指定的版本
。
下面的配置类示范了@ConditionalOnJava注解的用法。
@Configuration(proxyBeanMethods = false)
public class FkConfig
{
@Bean
// 只有当目标平台的Java版本是11或更新的平台时,该方法才生效
@ConditionalOnJava(value = JavaVersion.ELEVEN,
range = ConditionalOnJava.Range.EQUAL_OR_NEWER)
public DateFormat dateFormat()
{
return DateFormat.getDateInstance();
}
}
主启动类不变
上面粗体字注解要求目标平台的Java版本必须高于或等于11时,该配置才会生效。因此,只
有用Java11或更新版本的Java运行该程序,才会看到容器中的dateFormat Bean。
@ConditionalOnJndi注解要求指定JNDI必须存在
,使用该注解时通过value 属性指定要检查
的JNDI.
@ConditionalOnRepositoryType
注解要求特定的Spring Data Repository被启用时,其修饰的配
置类或方法才会生效。
3 springboot的web应用支持
3.2.3使用ClassPath扫描添加Servlet、Filter 或Listener
@ServletComponentScan @WebServlet、@WebFilter 和@WebListener
使用ClassPath扫描添加Servlet、Filter 或Listener的方式更加简单,开发者只要在Servlet类Filter类和Listener 类上分别添加@WebServlet、@WebFilter 和@WebListener注解,再通过@ServletComponentScan注解告诉Spring Boot自动扫描这些Web组件即可。