Springboot核心注解
运行文中的代码需要在项目构建中引入springboot 相关依赖.
① @configuration
configuration,用来将bean加入到ioc容器。代替传统xml中的bean配置。代码示例:
定义一个普通类:
public class Person {
}
定义一个配置类,用来将此类注册到ioc容器中:
@Configuration
public class PersonConfig { @Bean
public Person person(){
return new Person();
} }
测试类:
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(PersonConfig.class);
System.out.println(ac.getBean("person"));
}
}
运行结果:

② @ComponentScan
用来扫包,相当于xml配置的 :<context:component-scan base-package="" />
代码示例:
首先我们看一下项目的目录结构:

目前所有的类都是在CompentScanTest下面
一个普通的service bean:
@Service
public class UserService { }
一个配置类,这里会使用 @ComponentScan 注解:
@ComponentScan
public class ScanConfig { }
一个测试类:
public class CompentScanTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(ScanConfig.class);
Stream.of(ac.getBeanDefinitionNames()).forEach(System.out::println);
}
}
运行结果:

本包下的加了注解的类都被扫描了,也就是说 @ComponentScan 默认扫描本包下面加了对应注解的类。
可以添加一个熟悉 然后测试 :
@ComponentScan(basePackages = "com.llicat.stage3.springboot")
public class ScanConfig { }
此时把configuration包下的类也会扫描出来:

还有其他的像排除之类的,这里不在复述。
③ @EnableAutoConfiguration
主要有两个注解:

@import 的说明:
xml 中有如下配置:
<import resource="classpath:spring-dao.xml"/> 引入其他配置文件的配置。
代码结构:

一个简单对象类:
public class SimpleBean {
}
配置类,用来把对象加入ioc容器:
@Configuration
public class SimpleBeanConfig { @Bean
public SimpleBean simpleBean(){
return new SimpleBean();
}
}
测试类:
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(SimpleBeanConfig.class);
Stream.of(ac.getBeanDefinitionNames()).forEach(System.out::println);
System.out.println(ac.getBean("simpleBean"));
}
}
运行结果:

扫描了当前包下面存在注解的类。
在other包下面存在一个bean 和对应的配置类,我们修改一下代码:
@Configuration
@Import(OtherBeanConfig.class)
public class SimpleBeanConfig { @Bean
public SimpleBean simpleBean(){
return new SimpleBean();
}
}
然后运行发现,其他类也被扫描了。区别与compentScan @import 引入动态的配置类,可以使得扫描更加灵活和动态化


注意到这一个配置:

AutoConfigurationImportSelector实现了ImportSelector,importSelector是spring提供的一个用来支持动态注入的配置。这里可以模仿实现:
定义一个接口与两个实现类:
public interface Logger {
void doLogger();
}
public class DevLogger implements Logger {
@Override
public void doLogger() {
System.out.println("[DEBUG]...");
}
}
public class TestLogger implements Logger {
@Override
public void doLogger() {
System.out.println("[INFO]");
}
}
然后定义一个importSelector:
public class LoggerSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
Map<String, Object> include = importingClassMetadata.getAnnotationAttributes(EnableAutoSwitchLogger.class.getName());
Class [] clzs=null==include.get("include")?null:((Class[]) include.get("include"));
ArrayList<String> classList=new ArrayList<>();
Stream.of(clzs).forEach(clz->{
if(clz.isInterface()){
return;
}
classList.add(clz.getName());
});
return classList.toArray(new String[classList.size()]);
}
}
这个类主要是为了获取元数据信息,然后返回需要被扫描注入到ioc的类。
定义@EnableAutoSwitchLogger 并且使用LoggerSelector:
1 @Target(ElementType.TYPE)
2 @Retention(RetentionPolicy.RUNTIME)
3 @Documented
4 @Inherited
5 @Import(LoggerSelector.class)
6 public @interface EnableAutoSwitchLogger {
7
8 /**
9 * 这里可以指定要返回的日志实现类
10 * @return
11 */
12 Class<?>[] include() default {};
13 }
测试类:
1 @Configuration
2 @EnableAutoSwitchLogger(include ={TestLogger.class,DevLogger.class})
3 public class App {
4
5
6 public static void main(String[] args) {
7
8 AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(App.class);
9 Stream.of(ac.getBeanDefinitionNames()).forEach(System.out::println);
10 }
11
12 }
测试结果:

这个实际上就是springboot实现动态注入的一个关键点。分析AutoConfigurationImportSelector 的核心实现:
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
autoConfigurationMetadata, annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
点进去loadMetadata,会加载配置文件,其实就是条件注解,只有当前扫描的路径下存在条件中配置的类 然后去加载spring.factories中对应的第三方类。为了保证性能,不能是所有依赖的第三方的jar的类都被
加载,而是你配置了,才会去加载。
protected static final String PATH = "META-INF/"
+ "spring-autoconfigure-metadata.properties"; private AutoConfigurationMetadataLoader() {
} public static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
return loadMetadata(classLoader, PATH);
}
getAutoConfigurationEntry方法调用了getCandidateConfigurations 使用了 spring中的spi工具类SpringFactoriesLoader去加载配置文件META-INF/spring.factories中key为
org.springframework.boot.autoconfigure.EnableAutoConfiguration(注解的全限定名),对应的value会作为字符串被返回,然后作为需要被加载到ioc中的信息。spi是用来spring用来把第三方的jar包里面的类加载到
ioc容器的一种技术,需要满足指定路径下指定文件,且key匹配。@configuration 扫包扫不到第三方jar包。
总结:
@SpringBootApplication=@ComponentScan+@Configuration+@EnableAutoConfiguration
ComponentScan用来指定当前包路径,在这个路径下的都会被扫描到,@Configuration 用来说明这是一个配置类,可以去加载bean到ioc中。@EnableAutoConfiguration ,核心依AutoConfigurationImportSelector的实现:首先在META-INF/spring.factories 中预先配置了许多默认需要被加载的bean,然后在 spring-autoconfigure-metadata.properties配置了,这些默认bean被加载的条件,
并且通过条件可以过滤不需要被加载的bean,为了满足更大的客户化需求,在使用 @SpringBootApplication 可以指定 exclude属性,这些会作为元素数据,去移除掉不需要加载的类,同时也可以使用@ConditionalOnClass 去指定需要满足某些条件,默认配置中的类才会被加载。
Springboot核心注解的更多相关文章
- 浅谈SpringBoot核心注解原理
SpringBoot核心注解原理 今天跟大家来探讨下SpringBoot的核心注解@SpringBootApplication以及run方法,理解下springBoot为什么不需要XML,达到零配置 ...
- SpringBoot核心注解应用
1.今日大纲 了解Spring的发展 掌握Spring的java配置方式 学习Spring Boot 使用Spring Boot来改造购物车系统 2.Spring的发展 Spring1.x 时代 在S ...
- SpringBoot的核心注解和配置
一.入口类和SpringBootApplication Spring Boot的项目一般都会有*Application的入口类,入口类中会有main方法,这是一个标准的Java应用程序的入口方法. @ ...
- 【SpringBoot】15. Spring Boot核心注解
Spring Boot核心注解 1 @SpringBootApplication 代表是Spring Boot启动的类 2 @SpringBootConfiguration 通过bean对象来获取配置 ...
- SpringBoot 核心配置
1. 入口类和 @SpringBootApplication Spring Boot的项目一般都会有*Application的入口类,入口类中会有main方法,这是一个标准的Java应用程序的入口方法 ...
- springboot深入学习(一)-----springboot核心、配置文件加载、日志配置
一.@SpringBootApplication @SpringBootApplication是spring boot的核心注解,源码如下: 相当于:@Configuration+@EnableAut ...
- 最新学习springboot 配置注解
一.概述 Spring Boot设计目的是用来简化新Spring应用的初始搭建以及开发过程.Spring Boot并不是对Spring功能上的增强,而是提供了一种快速使用Spring的方式. ...
- SpringBoot核心
1.基本配置 1.1入口类和@SrpingBootApplication SpringBoot通常有一个名为*Application的入口类,入口类里有一个main方法,这个main方法就是一个标准的 ...
- 读懂这些spring boot的核心注解,快速配置完成项目搭建
在spring boot中,摒弃了spring以往项目中大量繁琐的配置,遵循约定大于配置的原则,通过自身默认配置,极大的降低了项目搭建的复杂度.同样在spring boot中,大量注解的使用,使得代码 ...
随机推荐
- 【Luogu】P1306 斐波那契公约数 题解
原题链接 嗯...很多人应该是冲着这个标题来的 (斐波那契的魅力) 1.分析题面 点开题目,浏览一遍题目,嗯?这么简单?还是蓝题? 再看看数据范围,感受出题人深深的好意... \(n,m \leq 1 ...
- 【Android 直播软件开发:音视频硬解码篇】
开篇 炙手可热,望而生畏的音视频开发 时至今日,短视频App可谓是如日中天,一片兴兴向荣.随着短视频的兴起,音视频开发也越来越受到重视,但是由于音视频开发涉及知识面比较广,入门门槛相对较高,让许许多多 ...
- 为什么要谨慎使用Arrays.asList、ArrayList的subList?
1. 使用Arrays.asList的注意事项 1.1 可能会踩的坑 先来看下Arrays.asList的使用: List<Integer> statusList = Arrays.asL ...
- git clone克隆github仓库慢,问题解决
导读 转载自:https://www.hangge.com/blog/cache/detail_2670.html 原因 由于国内网络问题,当我们使用 git clone 命令从 github ...
- 什么是JavaScript作用域
编程语言中,存储.访问和修改变量的值的能力将状态带给了程序.但是将变量引入程序会引起一些有意思的问题:变量存储在哪里?程序需要时如何找到它们?这些问题说明需要一套设计良好的规则来存储变量,并且之后可以 ...
- binary hacks读数笔记(堆、栈 VMA的分布)
一.首先看一个简单的程序: #include<stdlib.h> int main() { while(1) { sleep(1000); } return 0; } gcc -stati ...
- 双汇大数据方案选型:从棘手的InfluxDB+Redis到毫秒级查询的TDengine
双汇发展多个分厂的能源管控大数据系统主要采用两种技术栈:InfluxDB/Redis和Kafka/Redis/HBase/Flink,对于中小型研发团队来讲,无论是系统搭建,还是实施运维都非常棘手.经 ...
- java版飞机大战代码
@ 目录 前言 Plane PlaneStatus类 Power类 Gift Diji play类 over类 MainFrame主类 MyZiDan DijiZiDan Before 前言 很久之前 ...
- Go语言实现excel导入无限级菜单结构
目录 需求 实现 测试 简单例子 复杂例子 需求 最近有一个需求,要实现一个无限级结构的树型菜单,差不多长下面这个样子 我们知道无限级实现思路都是用一个parent_id将各种层级串联起来,顶级的pa ...
- Vegas干货分享,如何制作霓虹灯效果
在各色各样的展会中,各种炫彩华丽的灯光和光影一直都能吸引到人们大量的关注.同样,在视频制作中,光线的气氛渲染也是常用的方法,常用也就代表着效果明显,也是很多刚学视频剪辑小伙伴们想要学习的一种方法. 今 ...