共计 4289 个字符,预计需要花费 11 分钟才能阅读完成。
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());
};
}
}