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. 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中的
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; CollectionexceptionReporters = 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
整个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条)