Spring 以及 Spring Boot源码简单分析

1、Spring IOC的执行流程和扩展点

 1)创建一个新鲜的BeanFactory工厂

 2)读取和解析配置文件,若想读取必须实现BeanDefinitionReader接口, 通过beanDefinition定义bean信息

 3)BeanFactoryPostProcesser对引用外部文件的值进行赋值。比如配置数据源引用properties时,它的赋值就是在这

 4)通过反射创建对象

 5)创建对象的过程为实例化—>填充属性—>设置Aware接口属性—>执行BeanPostProcesser的前置增强—>初始化执行bean的init方法—>执行BeanPostProcesser的后置增强—>完整对象。Spring AOP的入口也正在BeanPostProcesser中

 一个对象的创建过程

 

 

总结:想要成为一个框架,首先要考虑的一定是拓展性

Aware接口的作用:当Spring容器创建的bean对象在进行具体操作的时候,如果需要容器的其他对象,此时可以将对象实现Aware接口,来满足当前的需要

2、循环依赖

 

 

1)三个缓存对象在获取数据的时候,是按照什么顺序来获取的?

 先获取一级缓存,没有再获取二级缓存,没有再获取三级缓存,所以当前面的缓存中存在了对象那么后面就需要把缓存对象给清空

 2)如果只有一级缓存,能解决循环以来问题吗?

  不能,如果只有一级缓存,那么成品对象和半成品对象会放到一起,就没办法区分了,所以需要两个缓存来分别存放不同状态的对象,一级缓存放成品,二级缓存存放半成品

 3)如果只有两个缓存,能否解决循环依赖问题?

   如果对象的创建过程中不包含aop那么二级缓存就可以解决循环依赖问题,但是包含aop的话,必须使用三级缓存

 4)为什么添加了aop之后,就需要三级缓存来解决这个问题?

  • 三级缓存加了什么操作?添加了一个getEarlyReference()的方法
  • 在创建代理对象的时候,是否需要生成原始对象?需要
  • 当创建完成原始对象之后,后续又需要创建代理对象,那么对象在引用的时候应该使用哪一个?
    换句话说,就是一个beanName对应有两个对象(原始对象和代理对象)
    在整个容器中,有且仅能有一个同名对象,当需要生成代理对象的时候,就需要把代理对象覆盖原始对象
  • 程序是怎么知道在什么时候要进行代理对象的创建的呢?
    需要一个类似于回调的接口判断,当需要第一次对外暴露使用的时候,来判断当前对象是否需要去创建代理对象,getEarlyBeanRefenerce()方法的if判断,如果需要代理就返回代理对象,如果没有代理就返回原始对象
public void refresh() throws BeansException, IllegalStateException {
  synchronized (this.startupShutdownMonitor) {
    // Prepare this context for refreshing.
    /**
     * 前戏,做容器刷新前的准备工作
     * 1.设置容器的启动时间
     * 2.设置活跃状态为true
     * 3.设置关闭状态为false
     * 4.获取Enviroment对象,并加载当前系统的属性值到Enviroment对象中
     * 5.准备监听器和事件的集合对象,默认为空的集合
    */
	prepareRefresh();

	// Tell the subclass to refresh the internal bean factory.
    // 创建容器对象,DefaultListableBeanFactory
    // 加载xml配置文件的属性值到当前的工厂中,最重要的就是BeanDefinition
	ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

	// Prepare the bean factory for use in this context.
    // 为上下文准备beanfactory,对beanFactory的各种功能进行填充,如@Autowired,设置spel表达式解析器,设置编辑注册器,添加applicaionContextAwareprocessor处理器等等
	prepareBeanFactory(beanFactory);

	try {
		// Allows post-processing of the bean factory in context subclasses.
        // 执行后置处理器的相关操作
		postProcessBeanFactory(beanFactory);

		// Invoke factory processors registered as beans in the context.
        // 
		invokeBeanFactoryPostProcessors(beanFactory);

		// Register bean processors that intercept bean creation.
		registerBeanPostProcessors(beanFactory);

		// Initialize message source for this context.
		initMessageSource();

		// Initialize event multicaster for this context.
        // 初始化上下文中事件广播器
		initApplicationEventMulticaster();

		// Initialize other special beans in specific context subclasses.
        // 留给子类来初始化其他的bean
		onRefresh();

		// Check for listener beans and register them.
        // 在所有注册的bean这哦你查找listener bean,注册到消息广播器中
		registerListeners();

		// Instantiate all remaining (non-lazy-init) singletons.
        // 初始化剩下的非懒惰的bean
		finishBeanFactoryInitialization(beanFactory);

		// Last step: publish corresponding event.
        //完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程
		finishRefresh();
	}
  }
}

3、AOP

 只有当所有的通知执行完毕之后才会调用实际的方法,而之前调用的advice只是为了指定通知的执行顺序,把链中的执行逻辑都罗列清楚,按照具体的方法进行返回操作

4、spring中用到哪种设计模式?

 1)单例模式:spring中bean都是单例的

 2)工厂模式:beanFactory

 3)模板模式:postProcessorBeanFactory,onRefresh

 4)装饰模式:BeanWrapper

 5)代理模式:aop动态代理

 6)观察者模式:Listener,event,multicast

 7)适配器模式: Adaper

 8)责任链模式:使用aop的时候,让通知 / 增强方法按照某种顺序执行

 9)委托模式:delegate

 10)建造者模式:builder

 11)策略者模式:XmlBeanDefinitionReader,PropertiesBeanDefinitionReader

5、Spring Boot

 环境准备:系统属性、web.xml中的<init-param>属性

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);
        // 设置系统环境以及servlet环境
		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;
}
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
		SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
	context.setEnvironment(environment);
	postProcessApplicationContext(context);
    // 
	applyInitializers(context);
	listeners.contextPrepared(context);
	if (this.logStartupInfo) {
        // 启动日志信息的打印工作
		logStartupInfo(context.getParent() == null);
		logStartupProfileInfo(context);
	}
	// Add boot specific singleton beans
	ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    // springApplicationArguments是run()方法里面的值,命令行参数
	beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
	if (printedBanner != null) {
		beanFactory.registerSingleton("springBootBanner", printedBanner);
	}
	if (beanFactory instanceof DefaultListableBeanFactory) {
		((DefaultListableBeanFactory) beanFactory)
					.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
	}
	if (this.lazyInitialization) {
		context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
	}
	// Load the sources
	Set<Object> sources = getAllSources();
	Assert.notEmpty(sources, "Sources must not be empty");

    // 自动装配的核心,一路load,里面有个registerBeanDefinition,注册主类
	load(context, sources.toArray(new Object[0]));
	listeners.contextLoaded(context);
}
整个springBoot有且仅有一个listeners,里面是包含了过滤后spring.factories文件中的监听对象


${random.int}

自动装配流程:

 1. run()方法里面有一个prepareContext()方法,它会加载当前的主程序类

 2. run()里面还有一个refreshContext()方法,这个是自动装配的入口,它最终会到Spring中AbstractApplicationContext中的refresh()方法,里面有一个invokeBeanFactoryPostProcessors()方法,它里面会扫描到主程序类的@Import注解里面的AutoConfigurationImportSelector类和AutoConfigurationPackages类,最终会执行到AutoConfigurationImportSelector类的getCandidateConfigurations()方法,然后会加载spring.factories中key=EnableConfiguration的信息,这就完成了自动装配,但是此时还没有实例化和初始化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值