springboot 自动装配
springboot最大特点就是自动装配
一.什么是自动配置?
根据特定条件自动将一些配置类的bean注册进ioc容器,使得可以在需要的地方直接从容器中获取和使用
? “自动”的表现形式就是我们只需要引我们想用功能的jar包,相关的配置我们完全不用管(springboot内置了很多的**start配置信息)
二.如何实现自动配置?
主要是依赖**@EnableAutoConfiguration**来实现的
1.spring boot启动run方法的时候,要有一个@SpringBootApplication注解的资源类(属于@Configuration),prepareContext方法时加载进容器
2.SpringBootApplication注解类上有一个@EnableAutoConfiguration
3.EnableAutoConfiguration注解类上有一个@Import(AutoConfigurationImportSelector.class)
4.spring创建上下文,会注册ConfigurationClassPostProcessor.class的BeanDefinition类定义(实现BeanDefinitionRegistryPostProcessor接口)到容器中
5.spring容器在刷新refresh的时候会调用invokeBeanFactoryPostProcessors(beanFactory)方法,实例化ConfigurationClassPostProcessor对象
6.有了ConfigurationClassPostProcessor对象,继续执行BeanDefinitionRegistryPostProcessor##postProcessBeanDefinitionRegistry的方法
7.BeanDefinitionRegistryPostProcessor##postProcessBeanDefinitionRegistry方法中,实例化ConfigurationClassParser对象并执行parser方法,操作容器中所有带注解的类(@SpringBootApplication),并找到@Import注解后面跟的value值,如果value值类型是DeferredImportSelector接口类型,放到集合中,循环执行getCandidateConfigurations方法
8.在AutoConfigurationImportSelector##getCandidateConfigurations(AnnotationMetadata metadata,AnnotationAttributes attributes)方法,里面有一行:List configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());注意loadFactoryNames方法的这两个参数!扫描所有jar包类路径下/META-INF/spring.factories文件中的EnableAutoConfiguration,能得到很多配置类(包括自定义的和org.springframework.boot.autoconfigure项目的所有)
9.在上面得到的很多List<String> configurations的,删除重复的、excluded的、过滤OnClassConditional、OnBeanConditional、OnWebApplicationConditional匹配不上的
10.然后触发AutoConfigurationImportEvent事件,告诉ConditionEvaluationReport条件评估报告器对象来分别记录符合条件和exclude的自动配置类,最后spring再将筛选成功后的类导入IOC容器中
11.org.springframework.boot.autoconfigure项目内置了很多的自动配置,所以如果需要使用这些配置,直接引用对应的jar包(或者引用对应的start jar包,效果一样的),其实spring-boot-starter-XXX这个项目也就是引入一下XXX需要的包而已,什么都没做,所以自动引用和使用start引用,没有什么区别
三.例子
在springboot之前,我们要在自己的spring应用中使用redis,要引入redis.clients、spring-data-redis两个引用,并在项目中自己设置配置
有了springboot后,只需要引入spring-boot-starter-redis一个引用,不用自己设置配置;或者引入redis.clients、spring-data-redis两个引用,不用自己设置配置
四.看一个真实的自动装配org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration(autoconfigure项目中,引入了很多的jar包依赖,但都是编译时依赖,打成的autoconfigure.jar包中,不会有对应的class类存在!)
解释上面几个注解:
1、@Configuration标注这个类是一个配置类
2、@ConditionalOnClass(RedisOperations.class):判断当前classpath下是否存在RedisOperations.class,若存在则将当前的配置类装载入spring容器
3、@ConditionalOnMissingBean(name = "redisTemplate"):判断当前spring容器中是否存在name为redisTemplate的对象,若不存在则将当前的对象装载入spring容器
org.springframework.boot.autoconfigure.data.redis.RedisProperties 提供了一些默认的配置信息
五.自定义start
自定义一个****start项目,写自己的***configuration和****properties,META-INF/spring.factories,key:org.springframework.boot.autoconfigure.EnableAutoConfiguration value值指向自己的***configuration,项目中引入自定义的start包即可