-- 阅读之前先掌握这个
- 常见的ApplicationContext: FileSystemXmlApplicationContext,ClassPathXmlApplicationContext,AnnoationConfigApplicationContext,ConfigurableApplicationContext,GenericApplicationContext(很多)
- 常见的Scanner:ClassPathBeanDefinationScanner,AnnotationBeanDefinitionScanner
java
// 创建容器
GenericApplicationContext applicationContext = new GenericApplicationContext();
// 确定bean类型
AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition(类).setScope(域).getBeanDefinition();
// 注册bean
applicationContext.registerBeanDefinition();
//启动IOC
applicationContext.refresh();
// ....
// 实现注解的各种方式
//....
applicationContext.close();
- AOP
java
// 设置proxyFactory
ProxyFactory proxyFactory = new ProxyFactory();
// 设置目标对象
proxyFactory.setTarget();
// 强制使用cglib
proxyFactory.setProxyTargetClass();
// 设置jdk动态代理
proxyFactory.setInterfaces();
// 设置通知
proxyFactory.addAdvice()
// proxyFactory.addAdvisor()配合DefaultPointcutAdvisor()
资源加载
java
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 加载各种个样的配置文件
this.resourceLoader = resourceLoader;
// 断言工具
Assert.notNull(primarySources, "PrimarySources must not be null");
// 加载类的(给IOC的)
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 判断web类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
// 从ApplicationContext初始化前读取的(springBoot特有的)
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 从监听器读取,横跨整个ApplicationContext生命周期(SpringBoot特有的方法)
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//主类推断(通过这个和primarySource就可以得出当前是不是主类加载)
this.mainApplicationClass = deduceMainApplicationClass();
}
web应用判断
Java
static WebApplicationType deduceFromClasspath() {
// 使用 classUtils 判断是不是WebFlux的类型
if ( ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) &&
!ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null) &&
!ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
// 返回一个Reactive类型项目
return WebApplicationType.REACTIVE;
}
// 判断是不是非Web类型
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
// 以上都不是即Servlet项目
return WebApplicationType.SERVLET;
}
spring.factories文件(SpringBoot的SPI原理)
- getSpringFactoriesInstances和createSpringFactoriesInstances这两个实际上就是创建和获取Spring.factories本质没有什么可讲的。
java
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = cache.get(classLoader);
if (result != null) {
return result;
}
result = new HashMap<>();
try {
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
String[] factoryImplementationNames =
StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
for (String factoryImplementationName : factoryImplementationNames) {
result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>())
.add(factoryImplementationName.trim());
}
}
}
// Replace all lists with unmodifiable lists containing unique elements
result.replaceAll((factoryType, implementations) -> implementations.stream().distinct()
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
cache.put(classLoader, result);
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
return result;
}
run方法核心原理
java
public ConfigurableApplicationContext run(String... args) {
// 统计启动时间
long startTime = System.nanoTime();
//创建DefaultBootstrapContext
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
// 创建ApplicationContext编译对象
ConfigurableApplicationContext context = null;
//
configureHeadlessProperty();
// 创建SpringApplicationRunListeners监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
// 开始监听
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 传入命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
// 控制台打印欢迎信息
Banner printedBanner = printBanner(environment);
// 赋值ConfigurableApplicationContext运行对象
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// 准备上下文
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 刷新上下文,启动SpringIOC
refreshContext(context);
// 回调操作
afterRefresh(context, applicationArguments);
// 计算耗时时间
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
//输出耗时日志
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
// 监听完毕
listeners.started(context, timeTakenToStartup);
// 查看CommandLineRunner和applicationRunner方法
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
// 处理启动异常
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
// 计算耗时时间
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
// 通知监听器,应用已经准备好
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
// 处理异常
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
// 返回已经创建好的上下文
return context;
}