组团学

@SpringBootApplication

阅读 (8374358)

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注解替换为三注解声明方式,代码如下:

//@SpringBootApplication @EnableAutoConfiguration//开启自动装配 @ComponentScan//包扫描 @Configuration//标识为配置类 public class FirstSpringbootApplication { public static void main(String[] args) { SpringApplication.run(FirstSpringbootApplication.class, args); } }

2.1.2 查看@SpringBootAppliction源码

@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源码

@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源码如下:

@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包下,修改启动类使控制器能正常访问

启动类代码如下:

@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为非引导类

非引导类代码如下:

@SpringBootApplication(scanBasePackages = {"com.tyschool.firstspringboot.controller"}) public class WebConfig { }

引导类代码如下:

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 代码如下:

@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()); }; } }
需要 登录 才可以提问哦