@SpringBootApplication
标注在哪个类上,就说明哪个类就是springboot的主配置类,springboot就会运行这个类中的main方法来启动 springboot的应用。
@SpringBootApplication主要有由
你要启动什么配置 我去加载配置 扫描注解
@EnableAutoConfiguration+@SpringBootConfiguration+@ComponentScan 三个注解组成@EnableAutoConfiguration 分别准备好了牛 羊 猪 鸭的做法 你拿了一只猪给@EnableAutoConfiguration接下来就是@SpringBootConfiguration拿着猪和猪的做法去做事情
A:@SpringBootConfiguration:springboot的配置类,标注在哪个类上,那么这个类就是springboot的配置类
@Configuration:Spring底层注解:
以前都是写配置文件[xml],现在写成一个个的配置类[java],所以要让spring知道这是一个配置信息,就用这个注解标注,实际上这个注解和@SpringBootConfiguration的含义差不多,只是一个是spring的一个是springboot的。
A-1:@Configuration 进去发现里面就是一个@Component[组件],也就是说配置类也是spring容器的组件
@Configuration:提到@Configuration就要提到他的搭档@Bean。使用这两个注解就可以创建一个简单的spring配置类,可以用来替代相应的xml配置文件。
<beans>
<bean id = "car" class="com.test.Car">
<property name="wheel" ref = "wheel"></property>
</bean>
<bean id = "wheel" class="com.test.Wheel"></bean>
</beans>
相当于:
@Configuration
public class Conf {
@Bean
public Car car() {
Car car = new Car();
car.setWheel(wheel());
return car;
}
@Bean
public Wheel wheel() {
return new Wheel();
}
}
@Configuration的注解类标识这个类可以使用Spring IoC容器作为bean定义的来源。@Bean注解告诉Spring,一个带有@Bean的注解方法将返回一个对象,该对象应该被注册为在Spring应用程序上下文中的bean。
Spring IoC容器:Spring IoC负责创建对象、管理对象(通过依赖注入(DI)、装配对象、配置对象,并且管理这些对象的整个生命周期。
B:@EnableAutoConfiguration:开启自动配置功能
B-1:@AutoConfigurationPackage:自动配置包;就是将主配置类[@SpringBootApplication标注的类]的所有在的包以及下面所有的组件扫描搭配spring容器中
@Import({Registrar.class})[spring底层注解,给容器中导入组件,导入的就是后面的类,Registrar进入看源码,谢谢]
B-2:@Import({EnableAutoConfigurationImportSelector.class}):EnableAutoConfigurationImportSelector导入哪些组件,找到这个类的父类[AutoConfigurationImportSelector]有一个方法,将所有需要导入的组件以全类名的方式返回,这些组件就会被添加到容器中,最终导入非常多的自动配置类[组件],例如aop等,有了自动配置类,就不需要手动编写配置注入功能组件等工作。
@EnableAutoConfiguration:能够自动配置spring的上下文,试图猜测和配置你想要的bean类,通常会自动根据你的类路径和你的bean定义自动配置。@EnableAutoConfiguration的作用启动自动的配置,@EnableAutoConfiguration注解的意思就是Springboot根据你添加的jar包来配置你项目的默认配置,比如根据spring-boot-starter-web ,来判断你的项目是否需要添加了webmvc和tomcat,就会自动的帮你配置web项目中所需要的默认配置;
@ComponentScan:会自动扫描指定包下的全部标有@Component的类,并注册成bean,当然包括@Component下的子注解@Service,@Repository,@Controller。是以前的<context:component-scan>(以前使用在xml中使用的标签,用来扫描包配置的平行支持),其实很简单,@ComponentScan主要就是定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中,ComponentScan做的事情就是告诉Spring从哪里找到bean
@SpringBootApplication分三个:
@EnableAutoConfiguration:从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器,说白就是扫描导入的jar中去扫描spring.factories配置文件,根据指定的配置文件的地址,把指定地址的类,导入到spring的容器里面
@SpringBootConfiguration:@SpringBootConfiguration继承自@Configuration,二者功能也一致,标注当前类是配置类,并会将当前类内声明的一个或多个以@Bean注解标记的方法的实例纳入到srping容器中,并且实例名就是方法名
@ComponentScan:@ComponentScan告诉Spring 哪个packages 的用注解标识的类 会被spring自动扫描并且装入bean容器,例如,如果你有个类用@Controller注解标识了,如果主配置上没有@ComponentScan,那么该Controller就不会被spring扫描到,更不会装入spring容器中,因此你配置的这个Controller也没有意义;
说白了就是<context:component-scan>
@EnableAutoConfiguration
其中最关键的要属@Import(AutoConfigurationImportSelector.class),借助AutoConfigurationImportSelector,@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。
借助于Spring框架原有的一个工具类:SpringFactoriesLoader的支持,@EnableAutoConfiguration可以智能的自动配置功效才得以大功告成!
在AutoConfigurationImportSelector类中可以看到通过 SpringFactoriesLoader.loadFactoryNames()
把 spring-boot-autoconfigure.jar/META-INF/spring.factories中每一个xxxAutoConfiguration文件都加载到容器中,spring.factories文件里每一个xxxAutoConfiguration文件一般都会有下面的条件注解:
@ConditionalOnClass : classpath中存在该类时起效
@ConditionalOnMissingClass : classpath中不存在该类时起效
@ConditionalOnBean : DI容器中存在该类型Bean时起效
@ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效
@ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效
@ConditionalOnExpression : SpEL表达式结果为true时
@ConditionalOnProperty : 参数设置或者值一致时起效
@ConditionalOnResource : 指定的文件存在时起效
@ConditionalOnJndi : 指定的JNDI存在时起效
@ConditionalOnJava : 指定的Java版本存在时起效
@ConditionalOnWebApplication : Web应用环境下起效
@ConditionalOnNotWebApplication : 非Web应用环境下起效
SpringFactoriesLoader
SpringFactoriesLoader属于Spring框架私有的一种扩展方案(类似于Java的SPI方案java.util.ServiceLoader),其主要功能就是从指定的配置文件META-INF/spring-factories加载配置,spring-factories是一个典型的java properties文件,只不过Key和Value都是Java类型的完整类名,比如:
example.MyService=example.MyServiceImpl1,example.MyServiceImpl2
对于@EnableAutoConfiguration来说,SpringFactoriesLoader的用途稍微不同一些,其本意是为了提供SPI扩展的场景,而在@EnableAutoConfiguration场景中,它更多提供了一种配置查找的功能支持,即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfig.EnableAutoConfiguration作为查找的Key,获得对应的一组@Configuration类。
SpringFactoriesLoader是一个抽象类,类中定义的静态属性定义了其加载资源的路径public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories",此外还有三个
静态方法:
loadFactories:加载指定的factoryClass并进行实例化。
loadFactoryNames:加载指定的factoryClass的名称集合。
instantiateFactory:对指定的factoryClass进行实例化。
在loadFactories方法中调用了loadFactoryNames以及instantiateFactory方法。
public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) {
Assert.notNull(factoryClass, "'factoryClass' must not be null");
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
List<String> factoryNames = loadFactoryNames(factoryClass, classLoaderToUse);
if (logger.isTraceEnabled()) {
logger.trace("Loaded [" + factoryClass.getName() + "] names: " + factoryNames);
}
List<T> result = new ArrayList<T>(factoryNames.size());
for (String factoryName : factoryNames) {
result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse));
}
AnnotationAwareOrderComparator.sort(result);
return result;
}
loadFactories方法首先获取类加载器,然后调用loadFactoryNames方法获取所有的指定资源的名称集合、接着调用instantiateFactory方法实例化这些资源类并将其添加到result集合中。最后调用AnnotationAwareOrderComparator.sort方法进行集合的排序
配置文件处理器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>