Spring Boot 编程思想|理解@SpringBootApplication

Spring Boot 编程思想|理解@SpringBootApplication

@SpringBootApplication注解语义

SpringBoot 2.1.9官方文档18. Using the @SpringBootApplication Annotation

Many Spring Boot developers like their apps to use auto-configuration, component scan and be able to define extra configuration on their “application class”. A single @SpringBootApplication annotation can be used to enable those three features, that is:

The @SpringBootApplication annotation is equivalent to using @Configuration, @EnableAutoConfiguration, and @ComponentScan with their default attributes, as shown in the following example

@SpringBootApplication被用于激活@EnableAutoConfiguration@ComponentScan@Configuration三个注解的特性。

  • @EnableAutoConfiguration负责激活Spring Boot的自动装配机制
  • @ComponentScan激活@Component 的扫描
  • @Configuration声明标注为配置类

注解源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
    ...
}

启动类代码

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

等同于

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class AppBootstrap {
    public static void main(String[] args) {
        SpringApplication.run(AppBootstrap.class, args);
    }
}

不过@ComponentScan增加了排除的FilterType实现

  • TypeExcludeFilter
    • SpringBoot 1.4引入,用于查找BeanFactory中已注册的TypeExcludeFilter Bean,作为代理执行对象
  • AutoConfigurationExcludeFilter
    • SpringBoot 1.5开始支持,用于排除其他同时标注@Configuration@Configuration @EnableAutoConfiguration的类

@SpringBootApplication属性别名

public @interface SpringBootApplication {

	/**
	 * ...
	 */
	@AliasFor(annotation = EnableAutoConfiguration.class)
	Class<?>[] exclude() default {};

	/**
	 * ...
	 * @since 1.3.0
	 */
	@AliasFor(annotation = EnableAutoConfiguration.class)
	String[] excludeName() default {};

	/**
	 * ...
	 * @since 1.3.0
	 */
	@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
	String[] scanBasePackages() default {};

	/**
	 * ...
	 * @since 1.3.0
	 */
	@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
	Class<?>[] scanBasePackageClasses() default {};

}

以上所有属性方法上都标有@AliasFor注解,它是用于桥接其他注解的属性。

比如重新设置basePackages属性

@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};

启动类代码

@SpringBootApplication(scanBasePackages = "com.huajie.springboot.sample.spring.application.config")
public class AppBootstrap {
    public static void main(String[] args) {
        SpringApplication.run(AppBootstrap.class, args);
    }
}

扫描包的路径将会修改成"com.huajie.springboot.sample.spring.application.config"指定路径

理解自动配置机制

SpringBoot 2.1.9官方文档49. Creating Your Own Auto-configuration

If you work in a company that develops shared libraries, or if you work on an open-source or commercial library, you might want to develop your own auto-configuration. Auto-configuration classes can be bundled in external jars and still be picked-up by Spring Boot.

Auto-configuration can be associated to a “starter” that provides the auto-configuration code as well as the typical libraries that you would use with it. We first cover what you need to know to build your own auto-configuration and then we move on to the typical steps required to create a custom starter.

自动装配类能打包到外部的jar文件中,并且被Spring Boot装载。同时自动装配也能被关联到starter中,这些starter提供自动装配的代码和关联的依赖。

49.1 Understanding Auto-configured Beans中继续介绍了SpringBoot自动装配底层实现与Spring Framework注解@Configuration和@Conditional的联系

Under the hood, auto-configuration is implemented with standard @Configuration classes. Additional @Conditional annotations are used to constrain when the auto-configuration should apply. Usually, auto-configuration classes use @ConditionalOnClass and @ConditionalOnMissingBean annotations. This ensures that auto-configuration applies only when relevant classes are found and when you have not declared your own @Configuration.

文中提到的 @ConditionalOnClass and @ConditionalOnMissingBean 是最常见的注解,顾名思义,当@ConditionalOnClass 标注在@Configuration类上时,当且仅当目标类存在于ClassPath下是才予以装配。

例如:redis自动装配类RedisAutoConfiguration

判断条件:

  • RedisOperations.class是否存在
    • 如果pom中引入了spring-boot-starter-redis,就会显示存在这个类
  • Spring Bean容器中是否存在redisTemplate
    • 如果不存在则使用默认的自动配置
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean(name = "redisTemplate")
	public RedisTemplate<Object, Object> redisTemplate(
			RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}
    ...

spring-boot-autoconfigurespring Boot核心模块(jar),其中提供了大量的内建自动装配@Configurtation类,它们统一存放在org.springframework.boot.autoconfigure包或者子包下面,同时这些类均配置在META-INF/spring.factories资源中:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JXx4XbS2-1570495212008)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1570451969023.png)]

...
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
...

创建自动配置类

1.启动类

package com.huajie.springboot.sample.spring.application.bootstrap;
...
@EnableAutoConfiguration
public class AppBootstrap {
    public static void main(String[] args) {
        SpringApplication.run(AppBootstrap.class, args);
    }
}

2.增加配置类WebConfiguration

package com.huajie.springboot.sample.spring.application.config;
...
@Configuration
public class WebConfiguration {

    @Bean
    public RouterFunction<ServerResponse> helloWorld() {
        return route(GET("/hello-world"),
                request -> ok().body(Mono.just("Hello,World"), String.class)
        );
    }

    @EventListener(WebServerInitializedEvent.class)
    public void onWebServerReady(WebServerInitializedEvent event) {
        System.out.println("当前 WebServer 实现类为:" + event.getWebServer().getClass().getName());
    }

}

3.创建自动配置类WebAutoConfiguration,并使用@Import注解导入WebConfiguration

package com.huajie.springboot.sample.spring.application.autoconfig;
...
/**
 * Web 自动装配类
 */
@Configuration
@Import(WebConfiguration.class)
public class WebAutoConfiguration {
}

4.在项目src/main/resource目录下新建META-INF/spring.factories

# 自动装配
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.huajie.springboot.sample.spring.application.autoconfig.WebAutoConfiguration

测试:

启动AppBootstrap类,在没有使用@ComponentScan的情况下可以装配到WebConfiguration

浏览器输入

http://127.0.0.1:8080/hello-world

参考

  • 《Spring Boot 编程思想》-小马哥
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值