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的信息,这就完成了自动装配,但是此时还没有实例化和初始化。