1.spring的版本进化特点
1.1SPRING框架1.X版本
开发人员大量编写xml配置文件,大量的bean标签的使用,实现set注入,构造方法注入等。
1.2SPRING框架2.X版本
转折:java出现了java5(jdk1.5)。出现新特性反射,枚举,注解。
spring转型:将xml中编写的配置文件,转向注解来开发,@Controller @Repository @Service @Component @Autowired。
开发习惯:允许开发人员将自定义的业务代码从xml转向代码注解。减少了xml编配内容。
但是第三方的一些内容,还是需要xml配置支持。例如Datasource 实现类ComboPooledDatasource。
注解+xml配置这种格式,出现最多的环境是spring2.x
1.3SPRING框架3.X版本
继续扩展注解,出现了一批新功能注解@Configuration @Bean @ComponetScan @Import等。
致力于将2.x中残存的那些配置xml逻辑,完全转向代码配置。
趋势:xml即将消失
1.4SPRING框架4.X/5.X版本
4.x出现了条件注解@Conditional.允许在将xml转向代码的同时,利用条件实现各种代码加载的逻辑。比如何时加载,何种条件满足下加载,何种条件不满足时加载
--springboot在条件注解的基础上,扩展了衍生了大量的条件子注解@ConditionalOnClass,实现了最终走向自动配置的全部准备——
5.X已经没有了xml约束文件。
2.spring3.X的重要注解
2.1@Confugration
类注解 ElementType.TYPE
运行时 RUNTIME加载
@Component 继承了@Component特性:类上加载这个注解,至少这个类在容器中一旦被扫描就可以创建bean对象。
- 作用:将一个类标识为一个配置类,等同于之前一个xml文件的位置。可以使用一个类,来代替xml使用
- 案例1:bean标签加载,和@Bean注解
- 加载xml的方式
- 准备xml
- 加载xml的方式
- 配置一个bean标签
- 准备bean对象类
- 测试代码,加载xml创建容器
- 加载配置类
- 准备一个配置类,使用@Configuration注解
- 使用加载配置类的方式启动容器
- @Bean配合@Configuration
代替之前xml编写格式,bean标签。代码底层原理是工厂bean加载。
- 案例2:component-scan 和@ComponentScan注解
- xml加载
- 修改xml配置文件
- xml加载
在xml中开启包扫描,扫描cn.tedu.bean
- 编写一个新的类Bean2
最终容器启动,bean2也创建。
- 配置类加载
- 修改配置类添加@ComponentScan注解
使用xml的扫描标签,将被扫描到的@Component注解所在类的bean对象创建到容器里,同样的配置类起到xml作用,也可以实现这个功能,需要使用一个注解@ComponentScan。
- 加载效果相同
bean1 bean2都出现了
- import标签
使用xml配置的结构中,可以将大量的配置逻辑标签,存放到一个xml配置文件的,但是为了方便维护,一般会区分不同技术,引入多个xml,最终让容器加载。
- 添加配置文件xml
- 编写新类Bean3
加载ac1.xml就没有ac2.xml的功能,反过来加载也一样,如何实现2个都加载呢?可以使用import标签。加载ac1.xml同时,导入性的读取ac2.xml
- 使用import标签
- 容器运行
加载的还是原有ac1.xml,通过import标签实现ac2.xml同时加载。
- 配置类@Import注解
如果配置类可以代替xml使用,他也可以导入其他配置类。
- 准备新的配置类
用这个配置类代替ac2.xml配置文件。
最终加载的还是第一个配置类MyConfiguration01,可以使用@Import注解从配置类导入其他配置类。实现和import标签相同的效果。
- 修改加载的配置类MyConfiguration01
- 最终效果
- 模拟想象一个springboot场景
springboot提前准备扩展了非常多的常见应用场景对应的配置类,代替原有手动编写的xml,比如datasource配置,mybatis的配置,redis配置。
只要要求我们使用时,准备一个注解@Import将他所编写的大量底层实现配置逻辑加载。就可以实现自动配置了。
分析:
我得有自己的配置类作为入口。
还得找到springboot给我提供的配置类。
还得找到我的配置import导入他的配置的线索。
3.SPRINGBOOT核心注解
启动类中添加的@SpringBootApplication
3.1观察原码
组合了三个注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
组合注解:注解通过继承组合的方式,可以同时具备多个注解的功能
3.2SpringBootConfiguration
他的原码
这个注解本身就是表示配置类注解@Configuration,有他在的类就是配置类。启动类添加这个注解之后,就变成了一个配置类。
其中run方法就包含了测试案例中启动spring容器,加载配置类的功能。返回对象就是容器上下文。
3.3SPRINGBOOT自动配置类
在当前libaray库中,可以找到org.springframework.boot.autoconfigure的jar包,这里包含了springboot当前版本提供的所有自动配置类代码。从中可以找到大量的**AutoConfiguration,目前2.2.5.RELEASE版本存在直接的226个自动配置类,间接加载的配置上千个。
3.4@EnableAutoConfiguration
这个注解也是核心注解,在启动类上添加的一个组合注解之一。作用主要是从我们的启动类加载springboot的自动配置类。所以你一旦启动springboot,就会完成他底层大量自动配置类的加载过程
**理解selector
@Import不光导入可以单个指定名字的配置类。
还可以批量导入,需要配置的是一个selector选择器,选择器会加载当前环境中一个spring.factories中所有自动配置类的全路径名称,返回的是String[] 从中拿到配置类最终加载
这个注解也是一个派生注解,其中的关键功能由@Import提供,其导入的AutoConfigurationImportSelector的selectImports()方法通过SpringFactoriesLoader.loadFactoryNames()扫描所有具有META-INF/spring.factories的jar包。spring-boot-autoconfigure-x.x.x.x.jar里就有一个这样的spring.factories文件。
4.条件注解和衍生注解
4.1条件注解@Conditional
spring4.x版本出现的
有一个关键属性 value 值是Condition条件类的反射对象。我们可以利用这个类的实现逻辑来完成非常多种的条件判断。
例如:
与poroperties属性有关的条件
根据某个key的存在或者不存在判断
根据某个前缀的key值存在或者不存在判断
与class类有关的条件
根据依赖中存在哪个class判断
根据依赖中必须不存在哪个class判断
。。。
4.2springboot条件的衍生注解
springboot在开发过程中,根据conditional的功能早就实现了非常多种的衍生注解
- @ConditionalOnClass
这个注解是类注解,和方法注解,在一个配置类中,这个注解的存在会使容器加载配置类的时候判断条件是否满足,当某个特定的class类存在于依赖中才会加载这个类或者方法。
4.3案例演示
使用容器加载一个配置类,这个配置类使用了条件注解ConditionalOnClass,满足条件,才加载,不满足就不加载,容器中根本不理会这个配置类。
- 添加一个条件注解的配置类
当前是一个配置类,但是由于条件注解的存在,要求classpath环境必须没有一个依赖类ConditionA存在才能满足条件,如果不满足,类是存在,则不加载这个配置类
- 扫描该配置类所在包
MyConfiguration01中扫描他
- 启动运行
idea不允许默认情况下在编译有问题时运行代码。修改启动配置
运行结果,由于conditionA类不存在,所以条件满足,
如果换一个条件使用CondionB当条件内容,然后在当前项目准备这个类。由于条件不满足,配置类不加载。
4.4其他衍生注解
@ConditionalOnBean:类和方法注解,当环境中存在某个类的容器bean对象时满足条件,当前配置类,或者方法就加载执行,反之不加载。
@ConditionalOnMissingBean
@ConditionalOnProperty:可以实现对特定属性特定值的判断,可以从存在不存在,前缀满足,包含某个值的角度,等于某个值,不等于某个值的角度实现条件的判断
@ConditionalOnWebApplication:当前容器必须是web应用,判断有没有servlet容器启动
@ConditionalOnNotWebApplication:当前容器必须不能是web应用,没有servlet容器
5.解读某个AutoConfiguration
DatasourceAutoConfiguration
@Configuration:当前类是一个配置类,如果配加载,和创建datasource的bean对象有关
@ConditionalOnClass({DataSource.class,EmbeddedDatabaseType.class}):当前配置类到低加载不加载取决于这个条件注解,满足条件则加载,不满足则不加载
条件:当前classpath下必须依赖DataSource这个类和EmbeddedDatabaseType.class.
@EnableConfigurationProperties:满足条件时,要加载datasource的属性,spring.datasource前缀。
**注意:当你不明白,记不住某个技术引入时调用的属性值
@Import:导入,当前配置类加载的同时,多加载2个配置类。
RedisAutoConfiguration
6.总结:
SpringBoot的自动配置原理:spingboot首先先广泛预写了大量的配置类,通过核心注解:@SpringBootApplication实现的,该注解包含了三个重要注解:
1.@SpringBootConfiguration 将类变成配置类
2.@ComponentScan 包扫描
3.@EnableAutoConfiguration 启动自动配置
sping容器会先加载应用程序中的bean,进行查缺补漏,条件性的创建需要的bean,通过注解@ConditionalOnBean或@ConditionalOnMissingBean实现过滤.