不断的学习,我们才能不断的前进
一个好的程序员是那种过单行线马路都要往两边看的人

SpringBoot

SpringBoot 自动装配

Spring Boot的自动装配是通过@EnableAutoConfiguration 实现的,可以将启动类下所有的component组件注册到容器中,通过 SpringFactoriesLoader 最终加载外部jar包下面的META-INF/spring.factories中的自动配置类实现自动装配,自动配置类其实就是通过@Conditional按需加载的配置类,想要其生效必须引入spring-boot-starter-xxx包实现起步依赖。

比如对于database属性,必须有username、password属性,如果没有则会连接不上数据源。在这种情况如果还进行数据源的装配,则会抛出异常,所以希望不装配数据源。使用Conditional注解,传入实现Condition接口,重写matches匹配的方法,返回true则进行装配,false则不装配。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 允许在上下文中注册额外的 bean 或导入其他配置类
@EnableAutoConfiguration // 启用 SpringBoot 的自动配置机制
// 扫描被@Component (@Service,@Controller)注解的 bean,注解默认会扫描启动类所在的包下所有的类,可以自定义不扫描某些 bean
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
	Class<?>[] exclude() default {};
	String[] excludeName() default {};

}

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {

}

public interface DeferredImportSelector extends ImportSelector {

}

// 获取所有符合条件的类的全限定类名,这些类需要被加载到 IoC 容器中
public interface ImportSelector {
    String[] selectImports(AnnotationMetadata var1);
}
	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) { // 判断是否打开自动装配
			return NO_IMPORTS;
		}
    // 获取所有需要装配的bean,会加载 META-INF/spring.factories里面的配置(每次启动不会加载所有的配置,会根据@ConditionalOnXXX 进行过滤)
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

SpringBoot 的启动流程

SpringBoot的启动执行的是SpringApplication.run方法,run方法里面实例化了SpringApplication 并调用了run方法。

@EnableCaching
@MapperScan("com.site.blog.my.core.dao")
@SpringBootApplication
public class MyBlogApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyBlogApplication.class, args);
    }
}

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
		return run(new Class<?>[] { primarySource }, args);
	}

    // 实例化SpringApplication 并执行run方法
	public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
		return new SpringApplication(primarySources).run(args);
	}
    // 被执行的run方法
    public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}
    

目录