@SpringBootApplication

2022-09-15 14:05:53 浏览数 (1)

1、自动装配概述

Spring Boot 自动装配会尝试着装载开发人员在应用的Class Path下添加的JAR文件依赖,比如当HSQLDB存在于应用的Class Path时,开发人员不需要手动配置数据库连接的Beans,而是由Spring Boot自动装配一个内存型的数据库。

激活自动装配的注解是@EnableAutoConfigure和@SpringBootApplication。

2、@SpringBootApplication

2.1 理解@SpringBootApplication注解语义

2.1.1 @SpringBootApplication概述

官方解释@SpringBootApplication等价于@EnableAutoConfiguration、@ComponetScan和@Configuration。其中@EnableAutoConfiguration负责激活Spring Boot自动装配机制,@ComponetScan激活@Componet的扫描,@Configuration声明被标注为配置类。

案例:

重构first-springboot应用在项目引导类中将@SpringBootApplication注解替换为三注解声明方式,代码如下:

代码语言:javascript复制
//@SpringBootApplication
@EnableAutoConfiguration//开启自动装配
@ComponentScan//包扫描
@Configuration//标识为配置类
public class FirstSpringbootApplication {

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

}
2.1.2 查看@SpringBootAppliction源码
代码语言:javascript复制
@Target(ElementType.TYPE) //表示此注解的标识范围为接口、类、枚举
@Retention(RetentionPolicy.RUNTIME) //元注解,表示注解不仅保存在class文件是,并且jvm加载class文件之后,仍然存在
@Documented //表示该注解会被javadoc工具记录
@Inherited //表示该注解会被子类继承
@SpringBootConfiguration //与@Configuration作用相似,标识为配置类
@EnableAutoConfiguration //开启自动装配
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })//从何处扫描Bean
public @interface SpringBootApplication {

@SpringBootApplication:@EnableAutoConfiguration、@ComponetScan和@SpringBootConfiguration的组合,不过@ComponetScan并非使用了默认值,而是添加了排除的TypeFilter实现:TypeExcludeFilter和AutoConfigurationExcludeFilter。

2.1.3 查看@SpringBootConfiguration源码
代码语言:javascript复制
@Target({ElementType.TYPE}) //表示此注解的标识范围为接口、类、枚举
@Retention(RetentionPolicy.RUNTIME) //元注解,表示注解不仅保存在class文件是,并且jvm加载class文件之后,仍然存在
@Documented //表示该注解会被javadoc工具记录
@Configuration //标识为配置类
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

@AliasFor注解:能够将一个或多个注解的属性"别名"放在某个注解中。

2.2 @SpringBootApplication属性别名

@SpringBootApplication源码如下:

代码语言:javascript复制
@Target(ElementType.TYPE) //表示此注解的标识范围为接口、类、枚举
@Retention(RetentionPolicy.RUNTIME) //元注解,表示注解不仅保存在class文件是,并且jvm加载class文件之后,仍然存在
@Documented //表示该注解会被javadoc工具记录
@Inherited //表示该注解会被子类继承
@SpringBootConfiguration //与@Configuration作用相似,标识为配置类
@EnableAutoConfiguration //开启自动装配
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) //从何处扫描Bean
public @interface SpringBootApplication {


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


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


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


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


	@AliasFor(annotation = Configuration.class)
	boolean proxyBeanMethods() default true;

}

案例:

重构first-springboot将HelloController移动到com.tyschool包下,修改启动类使控制器能正常访问

启动类代码如下:

代码语言:javascript复制
@SpringBootApplication(scanBasePackages = {"com.tyschool"})
public class FirstSpringbootApplication {

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

3、 @SpringBootApplication标注非引导类

案例:

将启动类上的@SpringBootApplication去掉,添加非引导类,在非引导类上标注@SpringBootApplication注解,修改SpringApplication.run()方法中的class为非引导类

非引导类代码如下:

代码语言:javascript复制
@SpringBootApplication(scanBasePackages = {"com.tyschool.firstspringboot.controller"})
public class WebConfig {
}

引导类代码如下:

代码语言:javascript复制
public class FirstSpringbootApplication {

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

4、 @SpringBootApplication “继承”@Configuration CGLIB提升特性

@SpringBootApplication 作为@Configuration的"派生"注解,同样继承其注解特性,其中最明显的是CGLIB提升。因为@Bean在@Componet类中与正常的Java对象语义相同,不存在CGLIB处理,而后在@Configuration中则执行了CGLIB提升

案例:

验证@SpringBootApplication CGLIB提升特性

WebConfig 代码如下:

代码语言:javascript复制
@SpringBootApplication
public class WebConfig {
		
    //定义路由,访问/helloworld,返回Hello,World
    @Bean
    public RouterFunction<ServerResponse> helloWorld() {
        return RouterFunctions.route(RequestPredicates.GET("/helloWorld"),
                request -> ServerResponse.ok().body(Mono.just("Hello,World"), String.class)
        );
    }
  	
  	//项目启动时,打印相关信息
    @Bean
    public ApplicationRunner runner(BeanFactory beanFactory){
        return args -> {
            System.out.println("当前hello Bean实现类为:" beanFactory.getBean("helloWorld").getClass().getName());
            System.out.println("当前 WebConfiguration Bean实现类为:" beanFactory.getBean(WebConfig.class).getClass().getName());
        };
    }
}

0 人点赞