Spring源码阅读之bean对象的创建过程
Spring源码阅读之bean对象的创建过程
Spring是通过IOC容器来管理对象的,该容器不仅仅只是帮我们创建了对象那么简单,它负责了对象的整个生命周期-创建、装配、销毁。这种方式成为控制反转(组件对象控制权的转移,从程序代码本身转移到了外部容器,容器创建完对象后注入组件中)。
Spring的核心的是容器,不过这个容器并不是唯一的,框架本身就提供了很多个容器的实现,大概分为两种类型:
- BeanFactory:最简单的容器,只能提供基本的DI(依赖注入)功能。
- ApplicationContext(应用上下文):继承自BeanFactory,它能提供更多企业级的服务,例如解析配置文本信息等等,这也是ApplicationContext实例对象最常见的应用场景。
简单说说这两种方式的区别:
- 原始的BeanFactory无法支持spring的许多插件,如AOP功能、Web应用
- ApplicationContext利用MessageSource进行国际化 并有着事件机制。
- ApplicationContext扩展了ResourceLoader(资源加载器)接口,从而可以用来加载多个Resource,而BeanFactory是没有扩展ResourceLoader
- 与BeanFactory通常以编程的方式被创建不同的是,ApplicationContext能以声明的方式创建,如使用ContextLoader。当然你也可以使用ApplicationContext的实现之一来以编程的方式创建ApplicationContext实例 。
- BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能发现一些存在的spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。
ApplicationContext 介绍
如果说BeanFactory是Sping的心脏,那么ApplicationContext就是完整的身躯了。ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能。在Beanfactory中,很多功能需要以编程的方式实现,而在ApplicationContext中则可以通过配置的方式实现。
ApplicationContext类体系结构:
在上一篇源码阅读WebContextApplication初始化中说到实际创建的对象为XmlWebApplicationContext
,该类继承了AbstractRefreshableWebApplicationContext
(上图的左下角),也是ApplicationContext体系。那么该对象读取配置文件后是如何创建bean对象的呢?
大致分为两步:
实例化BeanDefinition对象(下面分析该对象的作用) 。
实例化bean对象。
1. 实例化BeanDefinition对象
WebContextApplication初始化说到初始化的步骤是在ContextLoader
中完成,创建完XmlWebApplicationContext
对象后,通过configureAndRefreshWebApplicationContext()
设置配置文件的位置。
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {String configLocationParam;if (ObjectUtils.identityToString(wac).equals(wac.getId())) {configLocationParam = sc.getInitParameter("contextId");if (configLocationParam != null) {wac.setId(configLocationParam);} else {wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath()));}}//设置ServletContext环境。wac.setServletContext(sc);/*读取Servlet对象中的contextConfigLocation. ServletContext在创建的时候就读取了<context-param>标签,并将该标签中的配置文件的信息通过键值对的形式保存进来了。*/configLocationParam = sc.getInitParameter("contextConfigLocation");if (configLocationParam != null) {//保存配置文件信息的位置。wac.setConfigLocation(configLocationParam);}//刷新环境wac.refresh();}
配置文件位置设置完成后就需要读取该文件的配置信息,并创建相应的bean对象,这一过程就是在refresh()
中完成的。
通过图中的继承关系往上寻找在AbstractApplicationContext
中发现·refresh
方法,
该方法进行一些初始化操作。
public void refresh() throws BeansException, IllegalStateException {synchronized(this.startupShutdownMonitor) {// 1.刷新前的预处理,包含设置启动时间、设置状态...this.prepareRefresh();//实现刷新BeanFactory,将配置文件解析为BeanDefinition并注册到BeanFactory,此时Bean还未被初始化ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();// BeanFactory的预准备工作this.prepareBeanFactory(beanFactory);try {this.postProcessBeanFactory(beanFactory);// 执行BeanFactoryPostProcessor的方法,BeanFactory的后置处理器 // 在BeanFactory标准初始化之后执行的this.invokeBeanFactoryPostProcessors(beanFactory);// 注册BeanPostProcessor(Bean的后置处理器),用于拦截bean创建过程this.registerBeanPostProcessors(beanFactory);// 初始化MessageSource组件(做国际化功能;消息绑定,消息解析).this.initMessageSource();// 初始化上下文的事件机制this.initApplicationEventMulticaster();// 可以用于子类实现在容器刷新时自定义逻辑初始化this.onRefresh();// 注册时间监听器,将ApplicationListener注册到容器中来this.registerListeners();// 初始化所有剩下的单实例bean,单例bean在初始化容器时创建。this.finishBeanFactoryInitialization(beanFactory);// 发布完成事件,结束初始化过程this.finishRefresh();} catch (BeansException var5) {this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var5);this.destroyBeans();this.cancelRefresh(var5);throw var5;}}}
obtainFreshBeanFactory
将配置文件解析为BeanDefinition并注册到BeanFactory中
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {// 主要是通过该方法完成IoC容器的刷新this.refreshBeanFactory();ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();if (this.logger.isDebugEnabled()) {this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);}return beanFactory;}
refreshBeanFactory
完成IOC容器的刷新,具体实现是在AbstractRefreshableApplicationContext
中,实际创建的的IOC容器为:DefaultListableBeanFactory
protected final void refreshBeanFactory() throws BeansException {//首先检查是否已经有beanFactory了,有就销毁if (this.hasBeanFactory()) {this.destroyBeans();this.closeBeanFactory();}try {// 创建IoC容器,也就是DefaultListableBeanFactoryDefaultListableBeanFactory beanFactory = this.createBeanFactory();beanFactory.setSerializationId(this.getId());this.customizeBeanFactory(beanFactory);//载入刚创建的IOC容器,具体实现在子类XmlWebApplicationCpntext中this.loadBeanDefinitions(beanFactory);synchronized(this.beanFactoryMonitor) {this.beanFactory = beanFactory;}} catch (IOException var5) {throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);}}
loadBeanDefinitions
装载刚创建的IOC容器,具体实现在XmlWebApplicationCpntext
中。
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {// 创建一个BeanDefinition阅读器,通过阅读XML文件,真正完成BeanDefinition的加载和注册XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);//beanDefinitionReaderde 初始化操作beanDefinitionReader.setEnvironment(this.getEnvironment());beanDefinitionReader.setResourceLoader(this);beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));this.initBeanDefinitionReader(beanDefinitionReader);this.loadBeanDefinitions(beanDefinitionReader);}
//方法重载
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {/*在上一篇文章中ContextLoader中的configureAndRefreshWebApplicationContext方法有这一段代码configLocationParam = sc.getInitParameter("contextConfigLocation");if (configLocationParam != null) {//保存配置文件信息的位置。wac.setConfigLocation(configLocationParam);}这里就是读取配置文件的信息,保存进数组中。*/String[] configLocations = this.getConfigLocations();if (configLocations != null) {String[] var3 = configLocations;int var4 = configLocations.length;for(int var5 = 0; var5 < var4; ++var5) {String configLocation = var3[var5];//具体的装载方法在XmlBeanDefinitionReaderreader.loadBeanDefinitions(configLocation);}}}
接下来看XmlBeanDefinitionReader
中的loadBeanDefinitions()
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {// 对配置文件进行编码处理return this.loadBeanDefinitions(new EncodedResource(resource));
}
//截取主要代码
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {try {//将配置文件转换成流对象InputStream inputStream = encodedResource.getResource().getInputStream();try {// 从InputStream中得到XML的解析源InputSource inputSource = new InputSource(inputStream);if (encodedResource.getEncoding() != null) {inputSource.setEncoding(encodedResource.getEncoding());}// 这里是具体的读取过程,var5等于新注册的BeanDefintion数量var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());} finally {inputStream.close();}}
具体的读取过程在doLoadBeanDefinitions()
中,该方法的主要作用就是:
- 一个是对XML文件进行DOM解析
- 一个是完成BeanDefinition对象的加载与注册
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {try {//把资源文件转换成Document对象Document doc = this.doLoadDocument(inputSource, resource);// 通过对Document对象的操作,完成BeanDefinition的加载和注册工作return this.registerBeanDefinitions(doc, resource);}Catch(){}}
看看registerBeanDefinitions()
具体完成了哪些操作:
- 创建DefaultBeanDefinitionDocumentReader用来解析Document对象。
- 获得容器中已注册的BeanDefinition数量
- 委托给DefaultBeanDefinitionDocumentReader来完成BeanDefinition的加载、注册工作。
- 统计新注册的BeanDefinition数量
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {// 1.BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();documentReader.setEnvironment(this.getEnvironment());// 2.int countBefore = this.getRegistry().getBeanDefinitionCount();// 3. 解析过程入口,BeanDefinitionDocumentReader只是个接口,具体的实现过程在DefaultBeanDefinitionDocumentReader完成documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));// 4.return this.getRegistry().getBeanDefinitionCount() - countBefore;}
接着看DefaultBeanDefinitionDocumentReader
中的registerBeanDefinitions()
该方法:
- 获得Document的根元素标签
- 真正实现BeanDefinition解析和注册工作
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {this.readerContext = readerContext;this.logger.debug("Loading bean definitions");//获取文档对象的子节点。Element root = doc.getDocumentElement();//真正的解析注册方法this.doRegisterBeanDefinitions(root);}
到这一步接下来就是对解析文档中的每一个标签节点,获取标签中的属性。创建AbstractBeanDefinition
对象,并将标签中属性保存进对象中。具体的步骤就不展示了。
综上步骤具体完成了以下操作:
创建IoC容器(DefaultListableBeanFactory)
加载解析XML文件(最终存储到Document对象中)
读取Document对象,并完成BeanDefinition的加载和注册工作
BeanDefinition 在 spring 中贯穿始终,spring 要根据 BeanDefinition 对象来实
例化 bean,只有把解析的标签,扫描的注解类封装成 BeanDefinition 对象,spring
**才能实例化 bean **
上面的步骤只是完成了AbstractApplicationContext中refresh()
这句话(心累…)
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
2. 实例化Bean对象
进入AbstractApplicationContext
中的finishBeanFactoryInitialization()
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {beanFactory.setTempClassLoader((ClassLoader)null);beanFactory.freezeConfiguration();// 实例化剩余的单例bean(非懒加载方式)// 注意事项:Bean的IoC、DI和AOP都是发生在此步骤beanFactory.preInstantiateSingletons();}
进入DefaultListableBeanFactory中的preInstantiateSingletons()方法:
- 通过beanName获取bean实例,如果获取到的实例不满足条件就看最后一行getBean(beanName);
- 核心代码 getBean(beanName);
@Overridepublic void preInstantiateSingletons() throws BeansException {if (this.logger.isDebugEnabled()) {this.logger.debug("Pre-instantiating singletons in " + this);}// 得到Bean定义名称List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// 触发所有非懒加载方式的单例bean的创建for (String beanName : beanNames) {// 遍历得到对应的bean定义信息RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);// 如果bean不是抽象的,而且是单例的,同时还不是懒加载的,则进行下面的操作if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {// 如果bean是一个工厂bean,则走下面的方法 ,和普通bean区别就是还可以生成beanif (isFactoryBean(beanName)) {Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {final FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}}else { // 普通bean走下面的方法getBean(beanName);}}}
进入AbstractBeanFactory通过doGetBean()方法获取Bean的实例(只展示关键代码)
通过getSingleton(beanName)方法去缓存中获取单例Bean(第一次初始化,缓存中不存在)
如果取出来的bean实例是factoryBean的实例,则需要从factoryBean中产生一个Bean对象
根据当前的beanfactory获取父一级的beanFactory,递归查找我们需要的Bean(Bean是早不到的,第一次初始化)
获取实例化Bean的BeanDefinition对象
一般是单例Bean,用匿名内部类的写法,创建单例Bean
@Overridepublic Object getBean(String name) throws BeansException {// 获取Bean的实例return doGetBean(name, null, null, false);}@SuppressWarnings("unchecked")protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {// 获取bean名称final String beanName = transformedBeanName(name);Object bean;// Eagerly check singleton cache for manually registered singletons.// 从缓存中获取单例beanObject sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) { //如果获取到单例bean,则走下面代码if (logger.isDebugEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.debug("Returning cached instance of singleton bean '" + beanName + "'");}}// 如果取出来的Bean实例是FactoryBean的Bean实例,则需要从FactoryBean实例中产生一个对象实例。bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {//如果没有获取到单例bean,则走下面代码try {// 获取要实例化的bean的BeanDefinition对象final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// 检查该BeanDefinition对象对应的Bean是否是抽象的checkMergedBeanDefinition(mbd, beanName, args);// 如果是单例的Bean,请下面的代码if (mbd.isSingleton()) { //匿名内部类的写法sharedInstance = getSingleton(beanName, () -> {try {// 创建单例Bean的主要方法return createBean(beanName, mbd, args);}catch (BeansException ex) {destroySingleton(beanName);throw ex;}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}return (T) bean; }
进一步看看
createBean()
具体实现在AbstractAutowireCapableBeanFactory
中@Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {//省略一些代码try {// 完成Bean实例的创建(实例化、填充属性、初始化)Object beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isDebugEnabled()) {logger.debug("Finished creating instance of bean '" + beanName + "'");}return beanInstance;} ****
doCreateBean完成Bean实例的创建(实例化、填充属性、初始化)
- bean初始化第一步,默认调用无参数构造实例化bean
- bean初始化第二步,填充属性(DI依赖注入发生在此步骤)
- bean初始化第三步,调用初始化方法,完成bean的初始化操作AOP发生在此步骤)
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.// 用BeanWrapper来持有创建出来的Bean对象BeanWrapper instanceWrapper = null;// 如果是单例的话,则先把缓存中的bean清除if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}// bean初始化第一步:默认调用无参构造实例化Bean// 构造参数依赖注入,就是发生在这一步// 为了下一步populateBean方法的属性注入做准备if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}// 实例化后的Bean对象final Object bean = instanceWrapper.getWrappedInstance();Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// Allow post-processors to modify the merged bean definition.synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}}// Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces like BeanFactoryAware.// 解决循环依赖的关键步骤boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));// 如果需要提前暴露单例Bean,则将该Bean放入三级缓存中if (earlySingletonExposure) {if (logger.isDebugEnabled()) {logger.debug("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}// 将刚创建的bean放入三级缓存中singleFactories(key是beanName,value是FactoryBean)addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}// Initialize the bean instance.Object exposedObject = bean;try {// bean初始化第二步:填充属性(DI依赖注入发生在此步骤)populateBean(beanName, mbd, instanceWrapper);// bean初始化第三步:调用初始化方法,完成bean的初始化操作(AOP发生在此步骤)exposedObject = initializeBean(beanName, exposedObject, mbd);} ****************************************** }
进入上面的initializeBean()方法:
- 应用BeanPostProcessor的postProcessBeforeInitialization方法在初始化之前被调用
- 执行初始化方法(先调用InitializingBean的afterPropertiesSet,再调用init-method属性指定的初始化方法,最后BeanPostProcessor的postProcessAfterInitialization)
- 应用BeanPostProcessor的postProcessAfterInitialization方法(AOP代理对象生成)在初始化之后被调用
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {/*判断beanName是哪个接口的的实现类如果bean是BeanNameAware接口的实现类会调用setBeanName方法、如果bean是BeanClassLoaderAware接口的实现类会调用setBeanClassLoader方法、如果是BeanFactoryAware接口的实现类会调用setBeanFactory方法,注入对应的属性值。*/invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {//应用BeanPostProcessor的postProcessBeforeInitialization方法wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {//执行初始化方法(先调用InitializingBean的afterPropertiesSet,再调用init-method属性指定的初始化方法)invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}if (mbd == null || !mbd.isSynthetic()) {//应用BeanPostProcessor的postProcessAfterInitialization方法(AOP代理对象生成)// AOP是等着对象创建完毕,在进行增强wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}
调用初始化方法invokeInitMethods()
- 判断是否是InitializingBean接口的实现类,如果是县初始化InitializingBean
- 如果不是则调用InitializingBean接口中的afterPropertiesSet方法
- 然后再初始化标签对应的init-method属性中的方法
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)throws Throwable {boolean isInitializingBean = (bean instanceof InitializingBean);// 如果是InitializingBean接口的实现类,则先初始化InitializingBean的实现类if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {if (logger.isDebugEnabled()) {logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");}if (System.getSecurityManager() != null) {try {AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {((InitializingBean) bean).afterPropertiesSet();return null;}, getAccessControlContext());}catch (PrivilegedActionException pae) {throw pae.getException();}}else {// 调用InitializingBean接口的afterPropertiesSet方法((InitializingBean) bean).afterPropertiesSet();}}// 然后再初始化<bean>标签对应的init-method属性中的方法if (mbd != null && bean.getClass() != NullBean.class) {String initMethodName = mbd.getInitMethodName();if (StringUtils.hasLength(initMethodName) &&!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&!mbd.isExternallyManagedInitMethod(initMethodName)) {// 调用自定义的初始化方法invokeCustomInitMethod(beanName, bean, mbd);}}}
在initializeBean方法中调用BeanPostProcessor的applyBeanPostProcessorsAfterInitialization方法
- 在初始化Bean的时候都会调用每一个配置的BeanPostProcessor的方法
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {Object result = existingBean;Iterator var4 = this.getBeanPostProcessors().iterator();do {if (!var4.hasNext()) {return result;}BeanPostProcessor beanProcessor = (BeanPostProcessor)var4.next();//bean初始化后调用result = beanProcessor.postProcessAfterInitialization(result, beanName);} while(result != null);return result;}
BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口。接口声明如下:
public interface BeanPostProcessor {//bean初始化方法调用前被调用Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;//bean初始化方法调用后被调用Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }
至此bean的初始化就完成了。
tProcessor)var4.next();
//bean初始化后调用
result = beanProcessor.postProcessAfterInitialization(result, beanName);
} while(result != null);
return result;}
BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口。接口声明如下:```java
public interface BeanPostProcessor {//bean初始化方法调用前被调用Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;//bean初始化方法调用后被调用Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
至此bean的初始化就完成了。
参考:https://www.jianshu.com/p/32dacf644062 作者:GGarrett
Spring源码阅读之bean对象的创建过程相关推荐
- Spring源码解析-实例化bean对象
spring加载配置文件,AbstractApplicationContext类中的refresh方法起着重要的作用. @Overridepublic void refresh() throws Be ...
- Spring源码解析:自定义标签的解析过程
2019独角兽企业重金招聘Python工程师标准>>> spring version : 4.3.x Spring 中的标签分为默认标签和自定义标签两类,上一篇我们探究了默认标签的解 ...
- JVM源码简析(楔子)-对象内存分配过程和PS回收器中YGC触发FGC的现象
前言 想要搞明白Java对象内存申请过程的原因,是因为第一次接触线上GC日志的时候,发现了一些很奇怪的现象,就是young gc触发了full gc.为了搞清楚这个现象,得先要来个测试去复现. 复现现 ...
- Spring源码阅读(一)——整体结构
Spring 总共大约有20个模块,由1300多个不同的文件构成. Spring源码阅读可以分为三个路线:IOC,AOP,外部组件. 个人主页:tuzhenyu's page 原文地址:Spring源 ...
- spring源码阅读(3)-- 容器启动之BeanFactoryPostProcessor
接着上文<spring源码阅读(2)-- 容器启动之加载BeanDefinition>,当spring加载完所有BeanDefinition时,并不会马上去创建bean,而是先配置bean ...
- 【Spring 源码阅读】Spring IoC、AOP 原理小总结
Spring IoC.AOP 原理小总结 前言 版本约定 正文 Spring BeanFactory 容器初始化过程 IoC 的过程 bean 完整的创建流程如下 AOP 的过程 Annotation ...
- Spring源码分析之Bean的创建过程详解
前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...
- Spring源码分析系列——bean创建过程分析(三)——工厂方法创建bean
前言 spring创建bean的方式 测试代码准备 createBeanInstance()方法分析 instantiateUsingFactoryMethod()方法分析 总结 spring创建be ...
- 我该如何学习spring源码以及解析bean定义的注册
如何学习spring源码 前言 本文属于spring源码解析的系列文章之一,文章主要是介绍如何学习spring的源码,希望能够最大限度的帮助到有需要的人.文章总体难度不大,但比较繁重,学习时一定要耐住 ...
最新文章
- GDCM:读取显式长度SQIVR的测试程序
- android圆形变方形动画,CSS3 简单的圆形/方形变形动画
- CSS布局技巧之——各种居中
- php打印出函数的内容吗,PHP打印函数集合详解以及PHP打印函数对比详解(精)
- 谷歌大改Transformer注意力,速度大涨,显存大降!
- PHP结合Redis来限制用户或者IP某个时间段内访问的次数
- Adversarial examples in the physical world论文解读
- 异常、模块、文件读写
- java arraydeque poll,Java ArrayDeque pollLast()方法
- Atitit alldiaryindex v1 t717 目录 1. Fix	1 2. Diary detail	1 2.1. Diary 1987---2016.12	1 2.2. Diary20
- 【数字信号处理】基于Matlab GUI数字均衡器设计【含Matlab源码 904期】
- 80x86段寻址的原因
- 泪目!java面试八股文是哪些
- 百度“有啊”困局之源:流量到交易的转化
- 计算机桌面图标变大,电脑桌面图标变大了怎么恢复?
- FireFoxOS 初体验
- heic格式怎么改成jpg?
- Redhat Enterprise Linux 6.5下安装Oracle11g R2
- 120M硬盘的jslinux
- 手把手教你升级Keil MDK的ARM编译器