目录
一.spring模块
- 底层core container就是ioc容器,其中beans主要是BeanFactory低级容器,context 其中ApplicationContext是高级容器,通过组合的形式依赖BeanFactory低级容器。core是一些StringUtils之类的通用类
- AOP面向切面编程
- Web springMvc之类的
- Data Access 中orm框架比如mybatis
....................................................................................................................................................
二. 项目中使用的地方
- 采用拓展版的SpringMvc + Spring + 自定义orm框架
- 项目实现了ServletContextListener(servlet这块代码不文不涉及),其中启动时会调用如下代码
// ioc容器启动
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(springConfigLocation);
// 存起来,后续springmvc处理url时会调用getBean。
ServletContext.INSTANCE.setApplicationContext(applicationContext);
- applicationContent配置中配置了自动扫描bean
....................................................................................................................................................
三.spring ioc启动流程
- 注意: 如果对spring一点基础都没有,请google下基本使用
1. 从ClassPathXmlApplicationContext开始分析
- ClassPathXmlApplicationContext是根据 xml 文件内容来构建 ApplicationContext
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(springConfigLocation);
2. ClassPathXmlApplicationContext继续关系
-
盗用参考文章1的简化版继续关系图
- 其中AbstractRefreshableApplicationContext持有DefaultListableBeanFactory beanFactory引用,也就是与低级容器组合,ApplicationContext高级容器提供更多更高级功能。
-
DefaultListableBeanFactory 顾名思义就是持有多个bean的list,其中持有多个BeanDefinition ,BeanDefinition 中保存了我们的 Bean 信息,比如这个 Bean 指向的是哪个类、是否是单例的、是否懒加载、这个 Bean 依赖了哪些 Bean 等等。
3.ioc启动过程分析
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
// 根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割)
setConfigLocations(configLocations);
if (refresh) {
// 核心方法
refresh();
}
}
4. refresh核心方法
- refresh是在ClassPathXmlApplicationContext父类AbstractApplicationContext实现
// 不叫Init就是因为你可以refresh刷新下
@Override
public void refresh() throws BeansException, IllegalStateException {
// 防止refresh还没结束,你又启动容器
synchronized (this.startupShutdownMonitor) {
// 步骤1. 准备工作,记录下容器的启动时间、处理配置文件中的占位符
prepareRefresh();
/**
* 步骤2. 将各个需要spring管理的bean通过BeanDefinition形式 注册到DefaultListableBeanFactory中,
* 说到底核心是一个 beanName-> beanDefinition 的 map,
* 项目定义了spring自动扫描bean,spring会将需要扫描的包底下
* 有@Component,@Service, @Controller等这些注解的扫描到注册到DefaultListableBeanFactory中
**/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 步骤3. 设置 BeanFactory 的类加载器,添加几个特殊的BeanPostProcessor,保证了这些需要先添加的顺序性链表结构
prepareBeanFactory(beanFactory);
try {
/**
* 步骤4. 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
* 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
**/
postProcessBeanFactory(beanFactory);
//步骤 5. 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法, 占位符解析就在这里。
invokeBeanFactoryPostProcessors(beanFactory);
/**
* 步骤6. 注册 BeanPostProcessor 的实现类包括aop的后置处理器也是在这里注册的,注意看和 BeanFactoryPostProcessor 的区别
* 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
* 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
**/
registerBeanPostProcessors(beanFactory);
// 步骤7. 初始化当前 ApplicationContext 的 MessageSource,国际化
initMessageSource();
// 步骤8. 初始化当前 ApplicationContext 的事件广播器
initApplicationEventMulticaster();
// 步骤9. 从方法名就可以知道,典型的模板方法(钩子方法),供拓展
onRefresh();
// 步骤10. 注册事件监听器,监听器需要实现 ApplicationListener 接口。
registerListeners();
// 步骤11. 初始化除懒加载外所有的单例beans,原型bean不会被报错到ioc容器,比较核心的代码
finishBeanFactoryInitialization(beanFactory);
// 步骤12. 最后,广播事件,ApplicationContext 初始化完成
finishRefresh();
}
catch (BeansException ex) {
// 异常处理省略
}
finally {
// 省略
}
}
}
5. 步骤1 prepareRefresh解析
- 这块比较简单就是些准备工作,记录下容器的启动时间、处理配置文件中的占位符
6. 步骤2 obtainFreshBeanFactory解析
- 初始化 BeanFactory(ioc容器)、加载 Bean、注册 Bean 等等。
- 看下AbstractApplicationContext.obtainFreshBeanFactory方法
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 创建新的 BeanFactory,加载 Bean 定义、注册 Bean 等等
refreshBeanFactory();
// 返回刚刚创建的 BeanFactory (省略部分Log代码)
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
return beanFactory;
}
- 继续看AbstractRefreshableApplicationContext.refreshBeanFactory方法
protected final void refreshBeanFactory() throws BeansException {
// 省略部分代码
try {
// 初始化一个 DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用
customizeBeanFactory(beanFactory);
// 核心方法,加载 Bean 到 BeanFactory 中
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
- 继续看重要方法AbstractXmlApplicationContext.loadBeanDefinitions
//此方法将通过一个 XmlBeanDefinitionReader 实例来加载各个 Bean
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 给这个 BeanFactory 实例化一个 XmlBeanDefinitionReader
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 重要方法
loadBeanDefinitions(beanDefinitionReader);
}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
// 关注loadBeanDefinitions方法
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
- 继续看AbstractBeanDefinitionReader.loadBeanDefinitions方法
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
// 这里我们只传一个location, classpath:applicationContext.xml
int counter = 0;
for (String location : locations) {
counter += loadBeanDefinitions(location);
}
return counter;
}
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
- 继续看XmlBeanDefinitionReader.loadBeanDefinitions方法
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
// 省略部分代码
try {
// 读取文件
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 重点关注
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
// 省略部分代码
}
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// xml文件解析成Document,org.w3c.dom里面的
Document doc = doLoadDocument(inputSource, resource);
// 重点关注
return registerBeanDefinitions(doc, resource);
}
catch (...
// 返回从当前配置文件加载了多少数量的 Bean
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
// 重点关注
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
- 继续看DefaultBeanDefinitionDocumentReader.registerBeanDefinitions
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
Element root = doc.getDocumentElement();
// 重点关注
doRegisterBeanDefinitions(root);
}
- 这里一个配置文件终于转换为一颗 DOM 树了,继续看DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions方法
protected void doRegisterBeanDefinitions(Element root) {
/**
* 我们看名字就知道,BeanDefinitionParserDelegate 必定是一个重要的类,它负责解析 Bean 定义,
* 这里为什么要定义一个 parent? 看到后面就知道了,是递归问题
* 因为 内部是可以定义 的,所以这个方法的 root 其实不一定就是 xml 的根节点,也可以是嵌套在里面的 节点,从源码分析的角度,我们当做根节点就好了
**/
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
/**
* 这块说的是根节点 中的 profile 是否是当前环境需要的,
* 如果当前环境配置的 profile 不包含此 profile,那就直接 return 了,不对此 解析
**/
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
preProcessXml(root); // 钩子
// 重要方法
parseBeanDefinitions(root, this.delegate);
postProcessXml(root); // 钩子
this.delegate = parent;
}
// default namespace 涉及到的就四个标签 、 、 和 ,
// 其他的属于 custom 的
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
// 我们这里要解析context:component-scan,所以直接看这个方法
delegate.parseCustomElement(root);
}
}
- 继续看BeanDefinitionParserDelegate.parseCustomElement方法
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
// 因为这里要解析标签context:component-scan,所以是ContextNamespaceHandler处理
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
// ContextNamespaceHandler父类NamespaceHandlerSupport处理
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 重点关注parse方法
return findParserForElement(element, parserContext).parse(element, parserContext);
}
- 调用ComponentScanBeanDefinitionParser.parse方法
public BeanDefinition parse(Element element, ParserContext parserContext) {
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
// 扫描basePackage包将所有含有@Component,@Service等几个注解的类扫描出来
// 通过BeanDefinition形式注册所有需要注册的bean到ioc容器
Set beanDefinitions = scanner.doScan(basePackages);
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
- 看下扫描的逻辑ClassPathBeanDefinitionScanner.doScan,这里面有扫描出来的bean放到ioc容器的操作
protected Set doScan(String... basePackages) {
// 这里我们只传了一个basePackage
Set beanDefinitions = new LinkedHashSet();
for (String basePackage : basePackages) {
Set candidates = findCandidateComponents(basePackage);
// 对扫描出来的bean进行注册到ioc容器处理
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 注册到ioc容器
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
// 看下注册到ioc那块代码
protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
//BeanDefinitionReaderUtils.registerBeanDefinition
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// 重要代码
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
//省略部分代码
}
// 实际处理是放到DefaultListableBeanFactory的beanDefinitionMap 里面
private final Map beanDefinitionMap = new ConcurrentHashMap(256);
- 到这里已经初始化了ioc 容器,
配置也相应的转换为了一个个 BeanDefinition,然后注册了各个 BeanDefinition 到ioc容器
7. 准备 Bean 容器: prepareBeanFactory
-Spring 对一些特殊的 bean 进行了处理
- 添加几个特殊的BeanPostProcessor,保证了这些需要先添加的顺序性链表结构
- 比如EmbeddedValueResolverAware,ApplicationContextAware
8. 第四第五点
- BeanFactoryPostProcessor是接触BeanDefinintion,可以在bean初始化化之前修改BeanDefinition。常见的PropertyPlaceholderConfigurer
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
- 注意 FactoryBean是在getBean中实现的
9.第六点
-
盗图参考文章第六点图, BeanPostProcessor注册作用
- 注意图中的InstantiationAwareBeanPostProcessor是BeanPostProcessor的子类,其中的postProcessBeforeInstantiation和postProcessAfterInstantiation都重载了,所以spring总体调用
- InitializingBean,FactoryBean, Aware, InstantiationAwareBeanPostProcessor解析
- InitializingBean源码: 初始化阶段一个个bean时会判断是否属于 InitializingBean,属于则回调
- SmartFactoryBean源码(继承自FactoryBean, 区别是前者启动时会注入ioc容器,后者第一次调用才会): 实现FactoryBean的接口不走正常的实例化,属性赋值,初始化流程,走refresh中preInstantiateSingletons另一个分支,如果isEagerInit设置为true那么启动时就初始化了。
- ApplicationContextAware源码:aware接口实现如EmbeddedValueResolverAware,ApplicationContextAware这些都是在实例化阶段调用postProcessBeforeInstantiation,set进行。初始化阶段会判断bean是否属于ApplicationContextAware,是则回调
- 自定义BeanPostProcessor源码: 在refresh的registerBeanPostProcessors方法中,会获取前面obtainFreshBeanFactory方法中获取到所有beanDefiniton的BeanPostProcessors类,拿出来注册到beanPostProcessors。然后在初始化阶段调用所有注册的BeanPostProcessors。
- InstantiationAwareBeanPostProcessor属于实例化的时候调用,这个aop会使用,分析aop的时候可以学习。
-
注意像这些postProcessor是每个类都会调用postProcessBeforeInstantiation,postProcessAfternstantiation方法的,像第四个是aop在使用,调用时会判断是否需要aop拦截生成代理类,不需要则跳过。上述3,4,5每个类初始化的都会调用对应postProcess方法,但是不属于对应的需要拦截的类都会跳过,像aop的AbstractAutoProxyCreator一样不属于需要aop拦截的都会过滤掉。aop中postProcessBeforeInstantiation(Class> beanClass, String beanName)是在实例化前调用,目的是先遍历所有bean, 找出@AspectJ类,把其中的增强器封装成Advisor加入list中。postProcessAfterInitialization(@Nullable Object bean, String beanName)是在初始化后调用的,目的是如果需要代理则返回代理类。
10. 初始化所有的 singleton beans
- 重点分析finishBeanFactoryInitialization方法,这里会负责初始化所有的 singleton beans。先是类A调用默认构造函数进行默认初始化,再是将各个属性赋值,如果对属性赋值过程中涉及别的类B初始化会重复这个过程,这时候因为持有类B的引用所以初始化真正完成。
- 看代码部分AbstractApplicationContext类下refresh 方法
// 初始化剩余的 singleton beans
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory){
// 省略部分代码
// 开始初始化剩下的 beanFactory.preInstantiateSingletons();
}
- DefaultListableBeanFactory. preInstantiateSingletons方法
public void preInstantiateSingletons() throws BeansException {
//省略部分代码
// 触发所有的非懒加载的 singleton beans 的初始化操作
for (String beanName : beanNames) {
// 非抽象、非懒加载的 singletons。如果配置了 'abstract = true',那是不需要初始化的
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 处理 FactoryBean
if (isFactoryBean(beanName)) {
if (isEagerInit) {
// 正常是走getBean
getBean(beanName);
}
}
else {
// 对于普通的 Bean,只要调用 getBean(beanName) 这个方法就可以进行初始化了
getBean(beanName);
}
}
}
}
- 继续看AbstractBeanFactory. getBean
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
// 我们在剖析初始化 Bean 的过程,但是 getBean 方法我们经常是用来从容器中获取 Bean 用的
@SuppressWarnings("unchecked")
protected T doGetBean(
final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 如果 args 不为空的时候,那么意味着调用方不是希望获取 Bean,而是创建 Bean
if (sharedInstance != null && args == null) {
// 下面这个方法:如果是普通 Bean 的话,直接返回 sharedInstance
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 这里走else分支,因为这里是要分析创建bean
else {
/*
* 到这里的话,要准备创建 Bean 了,对于 singleton 的 Bean 来说,容器中还没创建过此 Bean;
* 对于 prototype 的 Bean 来说,本来就是要创建一个新的 Bean。
*/
try {
// 先初始化依赖的所有 Bean,这个很好理解。
// 这里的依赖指的是 depends-on 中定义的依赖
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 检查是不是有循环依赖,循环依赖后续会专门讲到
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册一下依赖关系
registerDependentBean(dep, beanName);
// 先初始化被依赖项
getBean(dep);
}
}
// 创建 singleton 的实例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory
- 接下来当然是分析 createBean 方法,AbstractAutowireCapableBeanFactory类里面的,专门针对@Autowire
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// 省略部分代码
// 确保 BeanDefinition 中的 Class 被加载
Class> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
}
// 重头戏,创建 bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
- 接下来看doCreateBean方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
// 省略部分代码
BeanWrapper instanceWrapper = null;
// 这里只是调用默认构造函数进行实例化,属性还没有赋值
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object exposedObject = bean;
try {
// 这一步也是非常关键的,这一步负责属性装配,因为前面的实例只是实例化了,属性并没有设值,这里就是设值
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 还记得 init-method 吗?还有 InitializingBean 接口?还有 BeanPostProcessor 接口?
// 这里就是处理 bean 初始化完成后的各种回调
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
}
- 接下来重点看下createBeanInstance,populateBean,initializeBean方法(调用spring xml中的init 方法,调用initlizible中afterProperty方法), 先看下createBeanInstance
//省略部分代码
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
//省略部分代码
// 确保已经加载了此 class
Class> beanClass = resolveBeanClass(mbd, beanName);
//是否第一次
boolean resolved = false;
//是否采用构造函数注入
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 无参构造函数
return instantiateBean(beanName, mbd);
}
}
// 判断是否采用有参构造函数
Constructor>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 构造函数依赖注入
return autowireConstructor(beanName, mbd, ctors, args);
}
// 调用无参构造函数
return instantiateBean(beanName, mbd);
}
- 选一个无参的构造看一下instantiateBean
// 省略部分代码
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(new PrivilegedAction
- bean属性注入populateBean (), 重点如果属性是跟别的类B组那么这里会调用类B的初始化,并且持有类B的引用,当类B初始化完成时,类A也完成了属性注入了。
// 省略部分代码
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
// bean的所有属性
PropertyValues pvs = mbd.getPropertyValues();
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 如果返回 false,代表不需要进行后续的属性设值,也不需要再经过其他的 BeanPostProcessor 的处理
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 这里就是上方曾经提到过得对@Autowired处理的一个BeanPostProcessor了
// 它会对所有标记@Autowired、@Value 注解的属性进行设值
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 设置 bean 实例的属性值
applyPropertyValues(beanName, mbd, bw, pvs);
}
- 最终都初始化完成之后,会放到ioc容器councurrent map缓存(DefaultSingletonBeanRegistry.singleObject, key是名称,value是实例对象)
单例getBean
- 本质上是从councurrent map缓存获取(DefaultSingletonBeanRegistry.singleObject, key是名称,value是实例对象)
循环依赖
- 三种循环依赖:
- 构造器的循环依赖:这种依赖spring是处理不了的,this .singletonsCurrentlylnCreation.add(beanName)将当前正要创建的bean 记录在缓存中
Spring 容器将每一个正在创建的bean 标识符放在一个“当前创建bean 池”中, bean 标识
:在创建过程中将一直保持在这个池中,因此如果在创建bean 过程中发现自己已经在“当前
创建bean 池” 里时,将抛出BeanCurrentlylnCreationException 异常表示循环依赖。 - 单例模式下的setter循环依赖:通过“三级缓存”处理循环依赖。
- 非单例循环依赖:对于“prototype”作用域bean无法处理,spirng没有缓存非单例的bean。
- 单例模式下bean:使用三级缓存
- singletonFactories : 进入实例化阶段的单例对象工厂的cache (三级缓存)
- earlySingletonObjects :完成实例化但是尚未初始化的,提前暴光的单例对象的Cache (二级缓存)
- singletonObjects:完成初始化的单例对象的cache(一级缓存)
- 分析一下“A的某个field或者setter依赖了B的实例对象,同时B的某个field或者setter依赖了A的实例对象”这种循环依赖的情况。A首先完成了初始化的第一步,并且将自己提前曝光到singletonFactories中,此时进行初始化的第二步,发现自己依赖对象B,此时就尝试去get(B),发现B还没有被create,所以走create流程,B在初始化第一步的时候发现自己依赖了对象A,于是尝试get(A),尝试一级缓存singletonObjects(肯定没有,因为A还没初始化完全),尝试二级缓存earlySingletonObjects(也没有),尝试三级缓存singletonFactories,由于A通过ObjectFactory将自己提前曝光了,所以B能够通过ObjectFactory.getObject拿到A对象(虽然A还没有初始化完全,但是总比没有好呀),B拿到A对象后顺利完成了初始化阶段1、2、3,完全初始化之后将自己放入到一级缓存singletonObjects中。此时返回A中,A此时能拿到B的对象顺利完成自己的初始化阶段2、3,最终A也完成了初始化,进去了一级缓存singletonObjects中,而且更加幸运的是,由于B拿到了A的对象引用,所以B现在hold住的A对象完成了初始化。
占位符替换PropertyPlaceholderConfigurer解析
classpath:/application.properties
- 步骤 5. 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 中解析的
- 最终会调用PlaceholderConfigurerSupport的doProcessProperties(),这个方法就会取出BeanFactory中的BeanDefinition,然后循环处理除了本身以外的bean的占位符替换
设计模式
建造者模式
- BeanDefinitionBuilder创建BeanDefinition
工厂方法
- 在Spring中,我们可以通过指定的工厂方法创建bean
代理模式
- spring aop就是用的代理模式,比如jdk动态代理,cglib代理
策略模式
- 策略定义了通过不同方式完成相同事情的几个对象。完成任务的方式取决于采用的策略。
- 作为Spring中的每个控制器,MultiActionController(已经过时)执行方法来响应提供的请求。策略用于检测应使用哪种方法。解析过程在MethodNameResolver实现中实现,例如在同一个包中的ParameterMethodNameResolver中。方法可以通过多个条件解决:属性映射,HTTP请求参数或URL路径。
模版方法
- 此模式定义了类行为的骨架,并将子步骤的某些步骤的延迟执行
- refresh方法就是个模版方法
原型模式
- bean作用域的文章中介绍了类似的概念(prototype)
- 此设计模式允许通过复制已存在的对象来创建一个对象的实例
public class PrototypeTest {
@Test
public void test() {
Robot firstRobot = new Robot("Droid#1");
Robot secondRobot = (Robot) firstRobot.clone();
assertTrue("Cloned robot's instance can't be the same as the"
+" source robot instance",
firstRobot != secondRobot);
assertTrue("Cloned robot's name should be '"+firstRobot.getName()+"'"
+" but was '"+secondRobot.getName()+"'",
secondRobot.getName().equals(firstRobot.getName()));
}
}
class Robot implements Cloneable {
private String name;
public Robot(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
观察者模式
- 将应用程序的上下文事件分派给适当的监听器的观察者
- spring发布订阅模式,可以找个例子实际看看,网上比较多,不展开
单例模式
- 这种比较多,不展开
适配器
- springmvc使用适配器模式把不同Handler适配在一起统一对外提供功能
装饰器
- mybatis提供的二级缓存就是用装饰器,装饰一级缓存,对外提供功能
命令模式
- 它允许将请求封装在一个对象内并附加一个回调动作(每次遇到所所谓的回调大家就只需要理解为一个函数方法就好,省的去浪费那么多脑子)。请求被封装在命令对象之下,而请求的结果被发送到接收者。命令本身不是由调用者执行。
- 类似于输入linux命令最终都是由终端执行。客户端输入命令。
- 实践: 我们将多个方法最终执行某个底层方法
- spring中:
我要BeanFactory里面得到对象(也就是为了得到一个命令的执行结果),那么,想要在得到对象的时候就已经实现了一些对其修改的想法,那么就通过后置处理器,也是就实现了后置处理器接口的beans(命令里可以通过传入不同的参数来得到不同结果,或者对命令的脚本进行修改),然后还需要一个执行者(我们在做自动化运维的时候,不止操作一个脚本,这里的PostProcessorRegistrationDelegate就是集中来管理这些的),最后得到的结果就由BeanFactory来展示咯
访问者模式
- 抽象一点就是通过另一种类型的对象来使一个对象访问,需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,使用访问者模式将这些封装到类中。
- 可参考 访问者模式
....................................................................................................................................................
参考文章
- 最详细的Spring核心IOC的源码分析
- 【一叶知秋】Spring 源码解析五个spring用到的设计模式
- 面试问烂的 Spring IOC 过程,里面getBean分析还可以
- SpringIOC源码解析(上)
- SpringIOC源码解析(下)
- 别再问Spring Bean的生命周期了!
- spring是如何解决循环依赖的
- Spring自定义占位符替换(PropertyPlaceholderConfigurer解析)