框架源码系列八:Spring源码学习之Spring核心工作原理(很重要)
目录:
一、搞清楚ApplicationContext实例化Bean的过程
二、搞清楚这个过程中涉及的核心类
三、搞清楚IOC容器提供的扩展点有哪些,学会扩展
四、学会IOC容器这里使用的设计模式
五、搞清楚不同创建方式的bean的创建过程
一、ApplicationContext实例化bean的过程
1. 找入口,扫描注册完beanDefinition后,要创建bean的实例,入口在哪里?
AnnotationConfigApplicationContext context4 = new AnnotationConfigApplicationContext("com.study.leesmall.spring.service");
/**
* Create a new AnnotationConfigApplicationContext, scanning for bean definitions
* in the given packages and automatically refreshing the context.
* @param basePackages the packages to check for annotated classes
*/
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);
refresh();
}
org.springframework.context.support.AbstractApplicationContext.refresh()方法就是入口了
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh(); // Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context.
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.
onRefresh(); // Check for listener beans and register them.
registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event.
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
} // Destroy already created singletons to avoid dangling resources.
destroyBeans(); // Reset 'active' flag.
cancelRefresh(ex); // Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
2. 读懂org.springframework.context.support.AbstractApplicationContext.refresh()方法的处理流程
1)准备context为了刷新
// Prepare this context for refreshing.
prepareRefresh();
2)从子类获取BeanFactory实例
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
3)准备BeanFactory为了使用context
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
* @param beanFactory the BeanFactory to configure
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); // BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this); // Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); // Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
} // Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
重要1:
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)) 这段代码很重要:
如果你的bean实例里面需要ApplicationContext,你就需要实现ApplicationContextAwareProcessor这个接口,接口就会把ApplicationContext给到你的bean实例
也可以通过autowired注解去获取,因为下面的这段代码:
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
重要2:
注解方式加载配置
package com.study.leesmall.spring.ext; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.ReloadableResourceBundleMessageSource; @Configuration
@PropertySource("classpath:/application.properties")
public class MyConfiguration { @Bean("messageSource")
public ReloadableResourceBundleMessageSource getReloadableResourceBundleMessageSource() {
ReloadableResourceBundleMessageSource rms = new ReloadableResourceBundleMessageSource();
rms.setBasename("message");
return rms;
}
}
重要3:
参数配置的优先级:命令参数 > 环境变量 > properties 文件
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
命令参数配置方式:进入要运行的类——run as——run configurations——弹出如下界面——选择——Arguments——添加参数
环境变量参数配置方式:进入要运行的类——run as——run configurations——弹出如下界面——选择——Environment——添加参数
properties 文件参数配置方式:直接在Resource目录下加入properties文件里面加入参数——在application.xml配置加载properties文件即可
参数:
# jdbc properties
jdbc.driverClassName=xxxx
jdbc.url=xxxx
jdbc.username=xxxx
jdbc.password=xxxx
在application.xml配置加载properties文件
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:application.properties"/>
</bean>
4)对BeanFactory进行预处理
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
说明:这里用了模板方法设计模式,需要子类去实现的
5)调用执行BeanFactoryPostProcessor (这是一个很重要的扩展点,如果你想在Bean实例化前对BeanFactory进行处理的话,你就可以实现BeanFactoryPostProcessor接口及其子类如BeanDefinitionRegistryPostProcessor,示例如下面的排序优先级代码)
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
/**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before singleton instantiation.
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
委托给PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())执行
这里要注意一下Spring里面有很多类似这样的委托处理
代码详细解读:
说明:
BeanFactoryPostProcessor在实例化bean之前对BeanFactory进行处理的
BeanPostProcessor在bean实例化后,对bean进行处理的
这两个类用了观察者模式
AbstractApplicationContextrefresh模板方法模式
执行优先级:priorityOrded>orded
执行顺序示例:
优先排序的:
package com.study.leesmall.spring.ext; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.core.PriorityOrdered;
import org.springframework.stereotype.Component; @Component
public class MyBeanDefinitonRegistryPostProcessor3 implements BeanDefinitionRegistryPostProcessor, PriorityOrdered { @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("--- MyBeanDefinitonRegistryPostProcessor3.postProcessBeanFactory 被执行了。"); } @Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("--- MyBeanDefinitonRegistryPostProcessor3.postProcessBeanDefinitionRegistry 被执行了。");
} @Override
public int getOrder() {
return 1;
} }
普通排序的:
package com.study.leesmall.spring.ext; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component; @Component
public class MyBeanDefinitonRegistryPostProcessor2 implements BeanDefinitionRegistryPostProcessor, Ordered { @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("--- MyBeanDefinitonRegistryPostProcessor2.postProcessBeanFactory 被执行了。"); } @Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("--- MyBeanDefinitonRegistryPostProcessor2.postProcessBeanDefinitionRegistry 被执行了。");
} @Override
public int getOrder() {
return 0;
} }
没有排序的:
package com.study.leesmall.spring.ext; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.stereotype.Component; @Component
public class MyBeanDefinitonRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("--- MyBeanDefinitonRegistryPostProcessor.postProcessBeanFactory 被执行了。"); } @Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("--- MyBeanDefinitonRegistryPostProcessor.postProcessBeanDefinitionRegistry 被执行了。");
} }
运行结果:
--- MyBeanDefinitonRegistryPostProcessor3.postProcessBeanDefinitionRegistry 被执行了。
--- MyBeanDefinitonRegistryPostProcessor2.postProcessBeanDefinitionRegistry 被执行了。
--- MyBeanDefinitonRegistryPostProcessor.postProcessBeanDefinitionRegistry 被执行了。
--- MyBeanDefinitonRegistryPostProcessor3.postProcessBeanFactory 被执行了。
--- MyBeanDefinitonRegistryPostProcessor2.postProcessBeanFactory 被执行了。
--- MyBeanDefinitonRegistryPostProcessor.postProcessBeanFactory 被执行了。
6)向BeanFactory注册BeanPostProcessor(这是一个很重要的扩展点,如果你想在Bean实例化后对Bean进行处理的话)
registerBeanPostProcessors(beanFactory)
获得用户注册的BeanPostProcessor的bean定义,创建他们的实例,注册到BeanFactory,对bean实例化后进行处理
7)initMessageSource();初始化国际化资源文件
示例:
package com.study.leesmall.spring.ext; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.ReloadableResourceBundleMessageSource; //国际化 给入messageSource的bean实例到bean工厂
@Configuration
@PropertySource("classpath:/application.properties")
public class MyConfiguration { @Bean("messageSource")
public ReloadableResourceBundleMessageSource getReloadableResourceBundleMessageSource() {
ReloadableResourceBundleMessageSource rms = new ReloadableResourceBundleMessageSource();
rms.setBasename("message");
return rms;
}
}
8)initApplicationEventMulticaster 了解即可
初始化Application Event广播器,把所有事件广播出去
9)执行onRefresh(); 由子类来提供实现
10)registerListeners() (这是一个很重要的扩展点,如果你想对容器工作过程中发生的节点事件进行一些处理,比如容器要刷新、容器要关闭了,那么你就可以实现ApplicationListener)
注册ApplicationListener:获得用户注册的ApplicationListener的bean定义,创建他们的实例注册到第8步初始化的广播器上
示例代码:
package com.study.leesmall.spring.ext; import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component; //如果你想对容器工作过程中发生的节点事件进行一些处理,比如容器要刷新、容器要关闭了,那么你就可以实现ApplicationListener
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> { @Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("-----收到应用事件:" + event);
}
}
11)finishBeanFactoryInitialization(beanFactory); 完成剩余的单例bean的实例化,为了提前实例化,后面不用getBean去创建实例
a)什么时候实例化bean?
单例bean可以在启动时实例化好,这样能提高使用时的效率
原型bean在getBean(beanName)的时候实例化
b)单例bean和原型bean实例化的过程有区别吗?
没有区别的
c)Spring中支持的bean实例创建的方式有几种?分别如何配置的,如何来获取Bean实例的?
创建bean实例的方式:构造函数方式、工厂方式(静态工厂方式、非静态工厂方式)、实现FactoryBean的方式
工厂方式创建bean实例示例代码:
package com.study.leesmall.spring.sample.factory; import com.study.leesmall.spring.service.CombatService;
import com.study.leesmall.spring.service.LoveService;
import com.study.leesmall.spring.service.LoveServiceImpl; //工厂方式创建bean实例
public class LoveServiceFactory { //静态工厂方式创建bean实例
public static LoveService getLoveServiceFromStaticFactoryMethod() {
return new LoveServiceImpl();
} //非静态工厂方式创建bean实例
public CombatService getCombatServiceFromMemberFactoryMethod(int time) {
return new CombatService(time);
}
}
实现FactoryBean的方式创建bean实例示例代码:
package com.study.leesmall.spring.sample.factory; import org.springframework.beans.factory.FactoryBean; import com.study.leesmall.spring.service.LoveService;
import com.study.leesmall.spring.service.LoveServiceImpl; //实现FactoryBean的方式创建bean实例
public class LoveServiceFactoryBean implements FactoryBean<LoveService> { @Override
public LoveService getObject() throws Exception {
return new LoveServiceImpl();
} @Override
public Class<?> getObjectType() {
return LoveService.class;
} }
那么上面的创建bean实例的方式怎么在xm里面配置呢:
<!--静态工厂方式的配置 -->
<bean id="loveService" class="com.study.leesmall.spring.sample.factory.LoveServiceFactory"
factory-method="getLoveServiceFromStaticFactoryMethod">
<property name="combatService" ref="combatService"></property>
</bean>
<!--非静态工厂方式的配置 -->
<bean id="loveServiceFactory" class="com.study.leesmall.spring.sample.factory.LoveServiceFactory">
</bean>
<bean id="combatService" factory-bean="loveServiceFactory" factory-method="getCombatServiceFromMemberFactoryMethod">
<constructor-arg type="int" value="60" />
</bean>
<!--实现FactoryBean的方式的配置 -->
<bean name="loveService2" class="com.study.leesmall.spring.sample.factory.LoveServiceFactoryBean"></bean>
那么注解方式又怎么配置呢:
工厂方式创建bean实例注解配置:
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component; import com.study.leesmall.spring.service.CombatService;
import com.study.leesmall.spring.service.LoveService;
import com.study.leesmall.spring.service.LoveServiceImpl; //工厂方式创建bean实例
@Component
public class LoveServiceFactory { //静态工厂方式创建bean实例
@Bean
public static LoveService getLoveServiceFromStaticFactoryMethod() {
return new LoveServiceImpl();
} //非静态工厂方式创建bean实例
@Bean
public CombatService getCombatServiceFromMemberFactoryMethod(int time) {
return new CombatService(time);
}
}
实现FactoryBean的方式创建bean实例注解配置:
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component; import com.study.leesmall.spring.service.LoveService;
import com.study.leesmall.spring.service.LoveServiceImpl; //实现FactoryBean的方式创建bean实例
@Component
public class LoveServiceFactoryBean implements FactoryBean<LoveService> { @Override
public LoveService getObject() throws Exception {
return new LoveServiceImpl();
} @Override
public Class<?> getObjectType() {
return LoveService.class;
} }
代码跟踪:
入口:org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(ConfigurableListableBeanFactory)
数据类型的转换:
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
数据类型的转换对应在xml配置里面的写法:
<bean id="combatService" class="com.study.leesmall.spring.service.CombatService">
<constructor-arg type="int" value="60" />
</bean>
初始化内嵌值的解析器,如properties文件里面配置的值就需要这种解析器:
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
AOP:bean实例初始化后,在进行代理增强,不创建原始bean实例,直接创建代理子类的实例
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
提前实例化剩余的所有单例bean:
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
说明:看子类的实现,过程是找到单例bean的名称,然后getBean(beanName)拿到单例bean的实例
d)beanfactory中getBean()时的创建实例流程
代码跟踪:
入口:
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(String)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(String, Class<T>, Object[], boolean)
下面来看一下真正创建bean实例的方法
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(String, RootBeanDefinition, Object[]):
看一下org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(String, RootBeanDefinition, Object[])里面的org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(String, RootBeanDefinition)
方法:
然后看一下上面调用的org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation(Class<?>, String)方法:
注意:
这里又是一个扩展点, InstantiationAwareBeanPostProcessor 可以在 Bean 实例创建前、后进行增强处理
如果你想在bean实例创建前后进行处理可以继承InstantiationAwareBeanPostProcessor的子类InstantiationAwareBeanPostProcessorAdaper,然后覆写里面你需要实现的方法,创建前处理就实现创建前处理的方法
对比:
BeanPostProcessor可以在bean实例初始化前和初始化后进行处理
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(String, RootBeanDefinition, Object[])
->
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(String, RootBeanDefinition, Object[])
看一下org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(String, RootBeanDefinition, BeanWrapper)方法:
继续看一下创建bean实例的代码块:
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(String, RootBeanDefinition, Object[])
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(String, RootBeanDefinition, Constructor<?>[], Object[])
->
org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(String, RootBeanDefinition, Constructor<?>[], Object[])
说明:
explicitArgs:当你调用getBean的时候给定的造参数 spring在getbean的时候是可以自己传入构造参数的,可以不用bean定义里面指定或者xml里面配置的构造参数,示例如下:
getbean(“loveService”, .....)
拓展:
工厂Bean和Bean工厂的区别:
工厂Bean实现了FactoryBean接口的Bean
Bean工厂BeanFactory IOC容器
12)finishRefresh() 发布事件
二、 搞清楚这个过程中涉及的核心类
三、 搞清楚IOC容器提供的扩展点有哪些,学会扩展
1. 扩展点:如第一个大标题
一、ApplicationContext实例化bean的过程
中
2. 读懂org.springframework.context.support.AbstractApplicationContext.refresh()方法的处理流程
的5)、6)、10)步均为扩展点
5)调用执行BeanFactoryPostProcessor (这是一个很重要的扩展点,如果你想在Bean实例化前对BeanFactory进行处理的话,你就可以实现BeanFactoryPostProcessor接口及其子类如BeanDefinitionRegistryPostProcessor,示例如下面的排序优先级代码)
6)向BeanFactory注册BeanPostProcessor(这是一个很重要的扩展点,如果你想在Bean实例化后对Bean进行处理的话)
10)registerListeners() (这是一个很重要的扩展点,如果你想对容器工作过程中发生的节点事件进行一些处理,比如容器要刷新、容器要关闭了,那么你就可以实现ApplicationListener)
注册ApplicationListener:获得用户注册的ApplicationListener的bean定义,创建他们的实例注册到第8步初始化的广播器上
BeanDefinitionRegistryPostProcessor
BeanFactoryPostProcessor
BeanPostProcessorr
ApplicationListener
11)finishBeanFactoryInitialization(beanFactory); 完成剩余的单例bean的实例化,为了提前实例化,后面不用getBean去创建实例的
然后看一下上面调用的org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation(Class<?>, String)方法的讲解
注意:
这里又是一个扩展点, InstantiationAwareBeanPostProcessor 可以在 Bean 实例创建前、后进行增强处理
如果你想在bean实例创建前后进行处理可以继承InstantiationAwareBeanPostProcessor的子类InstantiationAwareBeanPostProcessorAdaper,然后覆写里面你需要实现的方法,创建前处理就实现创建前处理的方法
对比:
BeanPostProcessor可以在bean实例初始化前和初始化后进行处理
2. Spring容器启动时完成了哪几件核心事情:
1)Bean定义的获得(解析xml或者扫描注解)
2)环境的初始化 env
3)BeanDefinitionRegistryPostProcessor的自动发现与执行
4)BeanFactoryPostProcessor的自动发现与执行
5)BeanPostProcessorr的自动发现与注册
6)国际化资源初始化
7)事件广播器的初始化
8)ApplicationListener的自动发现与注册
9)实例化单例bean
四、 学会IOC容器这里使用的设计模式
模板方法设计模式、观察者模式(主要是这两个)、策略模式、工厂模式
搞清楚不同创建方式的bean的创建过程
完整代码获取地址:https://github.com/leeSmall/FrameSourceCodeStudy/tree/master/spring-source-study
框架源码系列八:Spring源码学习之Spring核心工作原理(很重要)的更多相关文章
- Spring Boot 项目学习 (四) Spring Boot整合Swagger2自动生成API文档
0 引言 在做服务端开发的时候,难免会涉及到API 接口文档的编写,可以经历过手写API 文档的过程,就会发现,一个自动生成API文档可以提高多少的效率. 以下列举几个手写API 文档的痛点: 文档需 ...
- Spring Boot 项目学习 (三) Spring Boot + Redis 搭建
0 引言 本文主要介绍 Spring Boot 中 Redis 的配置和基本使用. 1 配置 Redis 1. 修改pom.xml,添加Redis依赖 <!-- Spring Boot Redi ...
- 框架源码系列十一:事务管理(Spring事务管理的特点、事务概念学习、Spring事务使用学习、Spring事务管理API学习、Spring事务源码学习)
一.Spring事务管理的特点 Spring框架为事务管理提供一套统一的抽象,带来的好处有:1. 跨不同事务API的统一的编程模型,无论你使用的是jdbc.jta.jpa.hibernate.2. 支 ...
- spring源码系列(一)sring源码编译 spring源码下载 spring源码阅读
想对spring框架进行深入的学习一下,看看源代码,提升和沉淀下自己,工欲善其事必先利其器,还是先搭建环境吧. 环境搭建 sping源码之前是svn管理,现在已经迁移到了github中了,新版本基于g ...
- 3.2spring源码系列----循环依赖源码分析
首先,我们在3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖 中手写了循环依赖的实现. 这个实现就是模拟的spring的循环依赖. 目的是为了更容易理解spring源码 ...
- spring源码系列8:AOP源码解析之代理的创建
回顾 首先回顾: JDK动态代理与CGLIB动态代理 Spring中的InstantiationAwareBeanPostProcessor和BeanPostProcessor的区别 我们得知 JDK ...
- 【源码系列】Eureka源码分析
对于服务注册中心.服务提供者.服务消费者这个三个主要元素来说,服务提供者和服务消费者(即Eureka客户端)在整个运行机制中是大部分通信行为的主动发起者(服务注册.续约.下线等),而注册中心主要是处理 ...
- (2018干货系列八)最新VR学习路线整合
怎么学VR 即虚拟现实技术,是一种可以创建和体验虚拟世界的计算机仿真系统,它利用计算机生成一种模拟环境,是一种多源信息融合的.交互式的三维动态视景和实体行为的系统仿真使用户沉浸到该环境中.VR/AR/ ...
- Spring源码系列 — 注解原理
前言 前文中主要介绍了Spring中处理BeanDefinition的扩展点,其中着重介绍BeanDefinitionParser方式的扩展.本篇文章承接该内容,详解Spring中如何利用BeanDe ...
随机推荐
- [蓝点ZigBee] Zstack 之点亮LED灯 ZigBee/CC2530 视频资料
LED点灯实验,主要是依据Zstack 现有程序修改LED相关驱动,适配到我们自己的开发板上,我们开发板共有4个LED灯,其中一个是电源指示灯,剩余3个都是GPIO控制的LED灯,有LED 灯连接方式 ...
- 【DWM1000】 非官方开源定位代码bitcraze
蓝点DWM1000 模块已经打样测试完毕,有兴趣的可以申请购买了,更多信息参见 蓝点论坛 正文: 最近关注DWM1000 定位,一方面在看DWM1000 官方提供的代码,也在四处网上找资料看资料. 其 ...
- JDK 1.8 新特性
default 函数式接口 待总结
- python流程控制之if、 while和for 循环
1.if 语句 语法1 if 条件:# 代码1# ... # cls='human'# sex='female'# age=18## if cls == 'human' and sex == 'fem ...
- BZOJ4249 : Walls 防壁
首先可以将攻击位置整理成折线,答案不变. 对于一个长度为$k$的询问,若折线不超过两段,那么显然可以暴力贪心求解. 否则考虑折线中最短的一段$x\rightarrow y$,若其长度$\leq k$: ...
- tablespace(表空间) / segment(断) / extent(盘区)/ block(块)/datafile(文件)之间的关系
tablespace(表空间) / segment(断) / extent(盘区)/ block(块)之间的关系 tablespace : 一个数据库划分为一个或多个表逻辑单位,即表空间,每个表空 ...
- Vue(八)发送跨域请求
使用vue-resource发送跨域请求 axios不支持跨域 1 安装vue-resource并引入 cnpm install vue-resource -S 2 基本用法 使用this.$http ...
- C#轻量级配置文件组件EasyJsonConfig
一.课程介绍 一.本次分享课程<C#轻量级配置文件EasyJsonConfig>适合人群如下: 1.有一定的NET开发基础. 2.喜欢阿笨的干货分享课程的童鞋们. 二.今天我们要如何优雅解 ...
- javaScript系列 [01]-javaScript函数基础
[01]-javaScript函数基础 1.1 函数的创建和结构 函数的定义:函数是JavaScript的基础模块单元,包含一组语句,用于代码复用.信息隐蔽和组合调用. 函数的创建:在javaScri ...
- BIM轻量化助力建筑业迈向BIM+时代
多年以来,BIM一直是曲高和寡,仅仅在建筑圈内孤芳自赏.我们花那么多心思建了那么多BIM模型,如果仅仅在建筑圈内使用,未免暴殄天物.如何充分发掘BIM的价值,让更多的受众从BIM中受益,这是我们亟待解 ...