入门SpringBoot-关于启动原理(五)(转)
启动类:
- @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
从@SpringBootApplication开始入手,点击进入是以下代码:
@Target(ElementType.TYPE) // 注解的适用范围,其中TYPE用于描述类、接口(包括包注解类型)或enum声明 @Retention(RetentionPolicy.RUNTIME) // 注解的生命周期,保留到class文件中(三个生命周期) @Documented // 表明这个注解应该被javadoc记录 @Inherited // 子类可以继承该注解 @SpringBootConfiguration // 继承了Configuration,表示当前是注解类 @EnableAutoConfiguration // 开启springboot的注解功能,springboot的四大神器之一,其借助@import的帮助 @ComponentScan(excludeFilters = { // 扫描路径设置 @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { ... }
其中,最重要的三个注解是@SpringBootConfiguration 、@EnableAutoConfiguration、@ComponentScan
- @SpringBootConfiguration本质上还是@Configuration注解
@Configuration JavaConfig形式定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。简化了通过XML方式配置bean的方式,两者的区别如下:
- 表达形式层面
基于XML配置的方式是这样:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" default-lazy-init="true"> <!--bean定义--> </beans>
基于JavaConfig的配置方式是这样:
@Configuration public class MockConfiguration{ //bean定义 }
- 注册bean定义层面
基于XML配置形式
<bean id="mockService" class="..MockServiceImpl"> ... </bean>
基于JavaConfig的配置方式是这样:
@Configuration public class MockConfiguration{ @Bean public MockService mockService(){ return new MockServiceImpl(); } }
任何一个标注了@Bean的方法,其返回值将作为一个bean定义注册到Spring的IoC容器,方法名将默认成该bean定义的id。
- 表达依赖注入层面
基于XML中配置是这样:
<bean id="mockService" class="..MockServiceImpl"> <propery name ="dependencyService" ref="dependencyService" /> </bean> <bean id="dependencyService" class="DependencyServiceImpl"></bean>
基于java config是这样:
@Configuration public class MockConfiguration{ @Bean public MockService mockService(){ return new MockServiceImpl(dependencyService()); } @Bean public DependencyService dependencyService(){ return new DependencyServiceImpl(); } }
- @ComponentScan作用是自动扫描符合条件的组件,并最后加入到容器当中,默认情况下在@ComponentScan所在类的package扫描的,所以最好将启动类放在root package,默认不指定路径
- @EnableAutoConfiguration 包含以下几个注解
@SuppressWarnings("deprecation") @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(EnableAutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { ... }
其中,@AutoConfigurationPackage、 @Import(EnableAutoConfigurationImportSelector.class)是比较重要的两个注解
@AutoConfigurationPackage
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { @Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { register(registry, new PackageImport(metadata).getPackageName()); }
注册了一个Bean的定义,new PackageImport(metadata).getPackageName(),它其实返回了当前主程序类的 同级以及子级 的包组件。(这也是为什么把启动类放在根目录的原因)
@Import(EnableAutoConfigurationImportSelector.class)
EnableAutoConfigurationImportSelector.class继承AutoConfigurationImportSelector,AutoConfigurationImportSelector中selectImports方法,里面调用getCandidateConfigurations,getCandidateConfigurations里面通过
SpringFactoriesLoader读取META_INF/spring.factories文件的配置,并返回字符串数组
- @EnableAutoConfiguration 包含以下几个注解