说到Spring,似乎IOC、DI成为了我们的共鸣。工作中,Spring无处不在,如影随形,Spring给我们开发者带来了一个春天。这么优秀而美丽的框架,我想,源码是值得我们去深入学习的。
我使用的是spring-framework5.0.x版本,新建一个模块,作为自己的代码编写使用,需要在项目中已有的build.gradle文件引入一些配置和依赖,如下
plugins {
id 'java'
}
group 'org.springframework'
version '5.0.16.BUILD-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
//引入本次所需依赖模块 context模块包括了beans、aop、core、expression等
compile(project(":spring-context"))
}
//如果新建的模块没有java及resources使用如下进行创建
task 'create-dirs' {
doLast {
sourceSets*.java.srcDirs*.each {
it.mkdirs()
}
sourceSets*.resources.srcDirs*.each {
it.mkdirs()
}
}
}
appliationContent.xml
<bean id="messageService" name="m1,m2,m3" class="com.whp.service.impl.MessageServiceImpl">
<!--引入下面id为message的bean-->
<property name="message" ref="message"/>
</bean>
<bean id="message" class="com.whp.bean.Message"/>
Message.java
/**
* @author wanghp
* @version 1.0
* @date 2020/7/8 23:19
*/
public class Message {
public Message() {
//待会MessageServiceImpl注入Message会打印
System.out.println("instance Message Bean");
}
}
MessageServiceImpl.java
/**
* @author wanghp
* @version 1.0
* @date 2020/7/8 23:41
*/
public class MessageServiceImpl implements MessageService, BeanNameAware {
private Message message;
public MessageServiceImpl() {
//实例化MessageServiceImpl Bean会打印
System.out.println(" instance MessageServiceImpl Bean");
}
public void setMessage(Message message) {
this.message = message;
}
@Override
public String speak() {
System.out.println(message);
return "this is my test -->spring ioc ";
}
//BeanNameAware回调方法,其实还有BeanClassLoaderAware、BeanFactoryAware
@Override
public void setBeanName(String name) {
System.out.println("BeanNameAware:" + name);
}
}
Junit Test 也就是我们学习源码的入口,对于学习Spring找到一个入口是非常重要的。
@Test
public void XMLTest() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("appliationContent.xml");
MessageService messageService = (MessageService) applicationContext.getBean("messageService");
System.out.println(messageService.speak());
}
这是我新建测试的gradle模块列表结构
在进入ClassPathXmlApplicationContext构造方法之前,一般我们学习源码常用的2种方式,如下
1.ClassPathXmlApplicationContext:见名知意,基于类路径下的xml作为Spring容器初始化
2.AnnotationConfigApplicationContext:类似于SpringBoot启动加载,将主类传入构造方法。
这两种里面其实都是围绕refresh()里的13个方法展开的,本次我们使用第一种,基于xml的方式。
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
//因为 ApplicationContext 建立起来以后,其实我们是可以通过调用 refresh() 这个方法重建的,
// refresh() 会将原来的 ApplicationContext 销毁,然后再重新执行一次初始化操作。
refresh();
}
}
进入refresh()方法,先对里面的13个方法有个大概的印象。
@Override
public void refresh() throws BeansException, IllegalStateException {
//来个锁,不然你refresh()方法还没结束,你又来个启动或销毁的操作,岂不是乱套了?????
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
// 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
// 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
// 这块待会会展开说
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
// 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】
// 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
// 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了,不然没完没了了
initMessageSource();
// Initialize event multicaster for this context.
// 初始化当前 ApplicationContext 的事件广播器,这里也不展开了
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 从方法名就可以知道,典型的模板方法(钩子方法),
// 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
onRefresh();
// Check for listener beans and register them.
// 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,过
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 初始化所有的 singleton beans
//(lazy-init 的除外)
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 最后,广播事件,ApplicationContext 初始化完成
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.
// 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
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();
}
}
}
主要还是校验xml,设置一些初始化值…
protected void prepareRefresh() {
// 记录启动时间,
// 将 active 属性设置为 true,closed 属性设置为 false,它们都是 AtomicBoolean 类型
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// Initialize any placeholder property sources in the context environment.
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
// 校验 xml 配置文件
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
} else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 关闭旧的 BeanFactory (如果有),创建新的 BeanFactory,加载 Bean 定义、注册 Bean 等等
refreshBeanFactory();
// 返回刚刚创建的 BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
@Override
protected final void refreshBeanFactory() throws BeansException {
// 如果 ApplicationContext 中已经加载过 BeanFactory 了,销毁所有 Bean,关闭 BeanFactory
// 注意,应用中 BeanFactory 本来就是可以多个的,这里可不是说应用全局是否有 BeanFactory,而是当前
// ApplicationContext 是否有 BeanFactory
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 初始化一个 DefaultListableBeanFactory,为什么用这个,我们马上说。
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 用于 BeanFactory 的序列化,我想不部分人应该都用不到
beanFactory.setSerializationId(getId());
// 下面这两个方法很重要,别跟丢了,具体细节之后说
// 1.设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用
customizeBeanFactory(beanFactory);
//2.加载 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);
}
}
到了loadBeanDefinitions方法,他传入了个beanFactory,通过方法名,我们可以大概猜测到这个是加载BeanDefinition的,还是多个BeanDefinition,然后可能是放到beanFactory里。
对于BeanFactory也就是Bean工厂和这里的实现类DefaultListableBeanFactory肯定是有联系的,我们先来看一下这两者的UML图:
DefaultListableBeanFactory:由图我们可以发现,它几乎拥有了上面所有的能力,它的顶层几乎要么是接口,要么是抽象类,而对于DefaultListableBeanFactory而言,它就是一个实现类,拥有了顶层所有的能力,这也就是为什么DefaultListableBeanFactory是整个spring ioc的始祖,研究透它的前生今世对我们理解spring ioc的概念有着重要的作用。
BeanFactory:没什么好讲的,大致理解为Bean工厂吧,里面的一些方法无非就是通过各种传参类型获取Bean。
BeanDefinitionRegistry:如果一个类是BeanFactory的实现类,那么它就需要实现BeanDefinitionRegistry接口,原因很简单,Bean工厂需要个人帮他把外部的比如xml配置的,或者基于注解扫面的bean注册到Bean工厂,每个角色都有自己的职责,而不是BeanFactory什么都去做,体现了接口与的单一职责设计原则。
Q:到这里,那么会有一个面试题,BeanFactory和FactoryBean的区别?
A:先看个FactoryBean的几个实现类,相信你差不多知道答案了,
FactoryBean其实可以理解为Spring的一种灵活的应用,先看个简单案例:
xml:
<bean id="person" class="com.whp.service.impl.PersonFactoryBean">
<property name="personInfo" value="wanghp,100"/>
</bean>
PersonFactoryBean.java
public class PersonFactoryBean implements FactoryBean<Person> {
protected final Log logger = LogFactory.getLog(getClass());
private String personInfo;
public String getPersonInfo() {
return personInfo;
}
public void setPersonInfo(String personInfo) {
this.personInfo = personInfo;
}
@Override
public Person getObject() throws Exception {
if (logger.isDebugEnabled()) {
logger.debug("进入getObject");
}
logger.info("进入getObject");
Person person = new Person();
String[] split = personInfo.split(",");
person.setName(split[0]);
person.setAge(Integer.parseInt(split[1]));
return person;
}
@Override
public Class<?> getObjectType() {
logger.info("进入getObjectType");
return Person.class;
}
}
测试:
@org.junit.Test
public void FactoryBeanTest() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("appliationContent.xml");
Object person = applicationContext.getBean("&person");
System.out.println(person);//结果输出:com.whp.service.impl.PersonFactoryBean@88af592
Object personBean = applicationContext.getBean("person");//结果输出:com.whp.bean.Person@241ac1a4
System.out.println(personBean);
((Person) personBean).message();
//在Person类输出属性信息为:wanghp今年100岁啦
}
如果你在PersonFactoryBean的getObject方法,比如我把设置年龄改成person.setAge(3);
sout为:wanghp今年3岁啦 当然我也不可能3岁哈哈,题外话
所以一个FactoryBean和你想要的普通Bean就是一念之间("&"),如果想具体了解这两者区别,小伙伴们可以自行查阅相关资料,我们回归正轨…
AbstractXmlApplicationContext.java
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
//重点在这里
loadBeanDefinitions(beanDefinitionReader);
}
上面无非就是设置beanDefinitionReader的环境,加载资源,实体分解器EntityResolver,有个概念为SAX,你就把它当作是一个将xml解析到javaBean的东西,进入loadBeanDefinitions方法
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
//这里不会进来,因为getConfigResources()就是返回Null
reader.loadBeanDefinitions(configResources);
}
//这个就是拿到我们前面ClassPathXmlApplicationContext构造传进来的xml文件名
String[] configLocations = getConfigLocations();
if (configLocations != null) {
//走这里
reader.loadBeanDefinitions(configLocations);
}
}
进入loadBeanDefinitions方法
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int counter = 0;
// 注意这里是个 for 循环,也就是每个文件是一个 resource
for (String location : locations) {
counter += loadBeanDefinitions(location);
}
// 最后返回 counter,表示总共加载了多少的 BeanDefinition
return counter;
}
再进入loadBeanDefinitions方法,下面这段代码是不是头皮发麻了,看我标记todo 那2行,前面通过
location也就是字符串"appliationContent.xml",把xml加载进来编程一个Resource,因为配置文件能传多个,所以是个数组,然后将其传到loadBeanDefinitions进行解析
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
//todo 核心部分在这里
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
int loadCount = loadBeanDefinitions(resources);
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
Resource resource = resourceLoader.getResource(location);
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}
进入loadBeanDefinitions方法
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
for (Resource resource : resources) {
//看这里
counter += loadBeanDefinitions(resource);
}
return counter;
}
再进去,然后到了这里,因为我们解析是xml,所以这个方法所在类为XmlBeanDefinitionReader
将传进来的resource构造放入EncodedResource,然后拿到InputStream二进制流,将其封装为一个InputSource对象,然后丢到doLoadBeanDefinitions方法,resource通过get又回到了原来姿态
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource);
}
// 用一个 ThreadLocal 来存放配置文件资源
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
System.out.println(Thread.currentThread().getName());
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
System.out.println("now threadName :"+Thread.currentThread().getName());
if (!currentResources.add(encodedResource)) {
System.out.println("insert if----"+Thread.currentThread().getName());
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
System.out.println("out if ----"+Thread.currentThread().getName());
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();
}
} catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
} finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
进入doLoadBeanDefinitions
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
//此处省略try{}catch代码
// 这里就不看了,将 xml 文件转换为 Document 对象
Document doc = doLoadDocument(inputSource, resource);
//TODO 解析及注册 BeanDefinition
return registerBeanDefinitions(doc, resource);
进入registerBeanDefinitions,原来的inputSource变为了Document,而resource还是原来的配方
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//TODO 单一职责原则,DefaultDocumentLoader执行得到doc,而这个BeanDefinitionDocumentReader就是逻辑处理类
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//todo 注册该xml前Bean 的数量
int countBefore = getRegistry().getBeanDefinitionCount();
//todo 加载及注册Bean
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
//todo 记录本次加载的 BeanDefinition 个数
return getRegistry().getBeanDefinitionCount() - countBefore;
}
继续进入registerBeanDefinitions
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
// 前面都是XML解析的准备阶段
// 核心部分开始
// 从 xml 根节点开始解析文件
doRegisterBeanDefinitions(root);
}
到这里,核心解析xml部分来了哈,进入doRegisterBeanDefinitions方法,传入的是Element
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
//TODO 委托给delegate解析
this.delegate = createDelegate(getReaderContext(), root, parent);
//判断当前Beans节点是否是默认命名空间
if (this.delegate.isDefaultNamespace(root)) {
// 这块说的是根节点 中的 profile 是否是当前环境需要的,
// 如果当前环境配置的 profile 不包含此 profile,那就直接 return 了,不对此 解析
//获取beans节点的profile属性 "profile"
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
//可以使用逗号或分号将当前beans标签指定为多个profile类型
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
//判断当前beans标签的profile是否被激活
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;
}
}
}
//解析前处理,留给子类实现
//pre和post里面目前没有具体实现,模板设计模式,一个类要么面向继承设计,要么就用final修饰
preProcessXml(root);
//看这里
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
进入parseBeanDefinitions方法,主要就是Element和Node一些转换,判断,目前我们xml是默认标签配置的,也就是bean开头,当然你也可以自定义配置,这需要去写自己的schemas及xsd
// default namespace 涉及到的就四个标签 、 、 和 ,
// 其他的属于 custom 的
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//TODO 对bean
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 {
delegate.parseCustomElement(root);
}
}
进入parseDefaultElement方法,就到了我们解析标签了,判断默认标签属于什么类型,找到对应解析方法,我们目前是解析标签的
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
//解析import标签
importBeanDefinitionResource(ele);
} else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
//解析alias标签
processAliasRegistration(ele);
} else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
//解析bean标签 看这里
processBeanDefinition(ele, delegate);
} else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
进入解析bean的对应方法,重点来了哈,各位提提精神…
到这里,才是真正的解析单个bean标签,变为一个javaBean,也就是我们这里的bdHolder,然后调用registerBeanDefinition注测我们的BeanDefinition,后面我们大概会讲一下这些概念,帮小伙伴们梳理一下这块内容
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 将 节点转换为 BeanDefinitionHolder,就是上面说的一堆
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
//TODO 终于出来了,纪念一下当前时间 2020-05-19 15:27
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 将bdHolder注册到bean工厂
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
} catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
// 注册完成后,发送事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
先看如何将一个标签内容变为BeanDefinitionHolder,进入parseBeanDefinitionElement方法,他这里使用的是BeanDefinitionParserDelegate解析器
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//解析 id属性
String id = ele.getAttribute(ID_ATTRIBUTE);
//解析 name属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//分割 name属性
List<String> aliases = new ArrayList<>();
// 将 name 属性的定义按照 “逗号、分号、空格” 切分,形成一个 别名列表数组,
// 当然,如果你不定义 name 属性的话,就是空的了
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
// 如果没有指定id, 那么用别名列表的第一个名字作为beanName
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
// 根据 ... 中的配置创建 BeanDefinition,然后把配置中的信息都设置到实例中,
// 细节后面细说,先知道下面这行结束后,一个 BeanDefinition 实例就出来了。
// 注意: 是一个 !!!!!!!!!!!!!!!!
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
// 到这里,整个 标签就算解析结束了,一个 BeanDefinition 就形成了。
if (beanDefinition != null) {
// 如果都没有设置 id 和 name,那么此时的 beanName 就会为 null,进入下面这块代码产生
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) { // 按照我们的思路,这里 containingBean 是 null 的
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
} else {
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
// 把 beanClassName 设置为 Bean 的别名
aliases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
} catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
// 返回 BeanDefinitionHolder
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
上面看注释就好,然后核心方法是parseBeanDefinitionElement,返回AbstractBeanDefinition的对象,先讲讲AbstractBeanDefinition,UML如下
至于这几个类的用法小伙伴们可以自行百度,网上这些类说明及注释很全面,只需要记住AbstractBeanDefinition是个抽象类,提供相对比较全面的属性,然后下面是常用的3个实现类。
进入parseBeanDefinitionElement方法,主要就是解析标签的一些属性放入到BeanDefinition中,bean标签没有的会采用默认的值,比如scope=“singleton”
@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
//解析class属性
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
try {
//创建用于承载属性的 AbstractBeanDefinition 类型的 GenericBeanDefinition
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//硬编码解析默认 bean 的各种属性
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
/**
* 下面的一堆是解析 ...... 内部的子元素,
* 解析出来以后的信息都放到 bd 的属性中
*/
//解析元数据
parseMetaElements(ele, bd);
//解析 lookup-method 属性
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//解析 replaced-method 属性
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//总结:无论look-up replaced-method都是构造了一个MethodOverride,
// 并最终记录在了AbstractBeanDefinition的methodOverrides属性中
//解析构造函数参数
parseConstructorArgElements(ele, bd);
//解析 property 子元素
parsePropertyElements(ele, bd);
//解析 qualifier 子元素
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
} catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
} catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
} catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
} finally {
this.parseState.pop();
}
return null;
}
总结一下parseBeanDefinitionElement方法如何产生BeanDefinitionHolder对象的
1.AbstractBeanDefinition:解析bean标签完了将标签属性封装在一个(也就是bd)
2.beanName:beanName只有一个,别名可以有多个,两者都是关联起来的。
3.aliasesArray:别名集合,对应bean标签的name属性
然后将1,2,3构造封装在BeanDefinitionHolder里
进入 BeanDefinitionReaderUtils 的registerBeanDefinition方法
/**
* 从下面面的代码可以看出,解析的 beanDefinition 都会被注册到 ,
* BeanDefinitionRegistry 类型的实例 registry 中,而对于 beanDefinition
* 的注册分成了两部分:通过 beanName 的注册以及通过别名的注册。
*/
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
//使用 beanName 做唯一标识注册
String beanName = definitionHolder.getBeanName();
//1.通过 beanName 注册 BeanDefinition
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
//2.注册所有的别名
// 如果还有别名的话,也要根据别名全部注册一遍,不然根据别名就会找不到 Bean 了
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
看看如何将BeanDefinitionHolder的BeanDefinition 注册吧,其实这部分看起来比较常,正常逻辑会走else的this.beanDefinitionMap.put(beanName, beanDefinition);这行代码,看到这里,就知道前面为什么会返回一个DefaultListableBeanFactory的bean工厂了吧,所以最后注册BeanDefinition是在Bean的始祖DefaultListableBeanFactory里面注册的,应证了我们最初的结论,这其实就是个推导到论证的过程。这部分目前只是单个bean注册到bean工厂的beanDefinitionMap过程。
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
//注册前的最后一次校验,这里的校验不同于之前的XML校验,
// 但是此校验非彼校验,之前的校验时针对于 XML 格式的校验,而此时的校验时针是对于 AbstractBean- Definition 的 methodOverrides 属性的。
//要是对于 AbstractBeanDefinition 属性中的**
//校验 methodOverrides 是否与工厂方法并存或者**
((AbstractBeanDefinition) beanDefinition).validate();
} catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
//因为 beanDefinitionMap 是全局变量,这里定会存在并发访问
// old? 还记得 “允许 bean 覆盖” 这个配置吗?allowBeanDefinitionOverriding
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
// 处理重复名称的 Bean 定义的情况
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
// 如果不允许覆盖的话,抛异常
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + existingDefinition + "] bound.");
} else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
// log...用框架定义的 Bean 覆盖用户自定义的 Bean
if (logger.isWarnEnabled()) {
logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
} else if (!beanDefinition.equals(existingDefinition)) {
//用新的 Bean 覆盖旧的 Bean
if (logger.isInfoEnabled()) {
logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
} else {
// 用同等的 Bean 覆盖旧的 Bean,这里指的是 equals 方法返回 true 的 Bean
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
//覆盖
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
// 判断是否已经有其他的 Bean 开始初始化了.
// 注意,"注册Bean" 这个动作结束,Bean 依然还没有初始化,我们后面会有大篇幅说初始化过程,
// 在 Spring 容器启动的最后,会 预初始化 所有的 singleton beans
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
} else {
// 最正常的应该是进到这个分支。
// Still in startup registration phase
// 将 BeanDefinition 放到这个 map 中,这个 map 保存了所有的 BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
// 这是个 ArrayList,所以会按照 bean 配置的顺序保存每一个注册的 Bean 的名字
this.beanDefinitionNames.add(beanName);
// 这是个 LinkedHashSet,代表的是手动注册的 singleton bean,
// 注意这里是 remove 方法,到这里的 Bean 当然不是手动注册的
// 手动指的是通过调用以下方法注册的 bean :
// registerSingleton(String beanName, Object singletonObject)
// 这不是重点,解释只是为了不让大家疑惑。Spring 会在后面"手动"注册一些 Bean,
// 如 "environment"、"systemProperties" 等 bean,我们自己也可以在运行时注册 Bean 到容器中的
this.manualSingletonNames.remove(beanName);
}
// 这个不重要,在预初始化的时候会用到,不必管它。
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
//TODO 重置所有的beanName对应的缓存
resetBeanDefinition(beanName);
}
}
不知道到了这里,还有多少小伙伴在坚持呢?
上面无非就是加载配置文件读标签然后将标签内容放入到BeanDefinition中,然后注册到beanFactory的beanDefinitionMap,说到这个注册,小伙伴千万别搞懵了,这里注册的是BeanDefinition,还不是我们平常用的Spring管理的Bean,对于BeanDefinition,他只是一个暂时存储bean标签信息,如果这个bean是单例还是多例,是懒加载还是非拦截在,看下面代码就明白了
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
// 我们可以看到,默认只提供 sington 和 prototype 两种,
// 很多读者可能知道还有 request, session, globalSession, application, websocket 这几种,
// 不过,它们属于基于 web 的扩展。
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
// 设置父 Bean,这里涉及到 bean 继承,不是 java 继承。请参见附录的详细介绍
// 一句话就是:继承父 Bean 的配置信息而已
void setParentName(@Nullable String parentName);
// 获取父 Bean
@Nullable
String getParentName();
//设置 Bean的类名称,将来是要通过反射来生成实例的
void setBeanClassName(@Nullable String beanClassName);
// 获取 Bean 的类名称
@Nullable
String getBeanClassName();
// 设置 bean 的 scope
void setScope(@Nullable String scope);
@Nullable
String getScope();
// 设置是否懒加载
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
// 设置该 Bean 依赖的所有的 Bean,注意,这里的依赖不是指属性依赖(如 @Autowire 标记的),
// 是 depends-on="" 属性设置的值。
void setDependsOn(@Nullable String... dependsOn);
// 返回该 Bean 的所有依赖
@Nullable
String[] getDependsOn();
// 设置该 Bean 是否可以注入到其他 Bean 中,只对根据类型注入有效,
// 如果根据名称注入,即使这边设置了 false,也是可以的
void setAutowireCandidate(boolean autowireCandidate);
// 该 Bean 是否可以注入到其他 Bean 中
boolean isAutowireCandidate();
// 主要的。同一接口的多个实现,如果不指定名字的话,Spring 会优先选择设置 primary 为 true 的 bean
void setPrimary(boolean primary);
// 是否是 primary 的
boolean isPrimary();
// 如果该 Bean 采用工厂方法生成,指定工厂名称。对工厂不熟悉的读者,请参加附录
// 一句话就是:有些实例不是用反射生成的,而是用工厂模式生成的
void setFactoryBeanName(@Nullable String factoryBeanName);
// 获取工厂名称
@Nullable
String getFactoryBeanName();
// 指定工厂类中的 工厂方法名称
void setFactoryMethodName(@Nullable String factoryMethodName);
// 获取工厂类中的 工厂方法名称
@Nullable
String getFactoryMethodName();
// 构造器参数
ConstructorArgumentValues getConstructorArgumentValues();
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
// Bean 中的属性值,后面给 bean 注入属性值的时候会说到
MutablePropertyValues getPropertyValues();
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
// 是否 singleton
boolean isSingleton();
// 是否 prototype
boolean isPrototype();
// 如果这个 Bean 是被设置为 abstract,那么不能实例化,
// 常用于作为 父bean 用于继承,其实也很少用......
boolean isAbstract();
int getRole();
@Nullable
String getDescription();
@Nullable
String getResourceDescription();
@Nullable
BeanDefinition getOriginatingBeanDefinition();
}
这断你可以理解为前面beanFactory不是拿到了,这里是填充一下其他的东西,把要的放进来,不要的忽视就ok了,具体看注释
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
// 设置 BeanFactory 的类加载器,我们知道 BeanFactory 需要加载类,也就需要类加载器,
// 这里设置为加载当前 ApplicationContext 类的类加载器
beanFactory.setBeanClassLoader(getClassLoader());
// 设置 BeanExpressionResolver
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
// 添加一个 BeanPostProcessor,这个 processor 比较简单:
// 实现了 Aware 接口的 beans 在初始化的时候,这个 processor 负责回调,
// 这个我们很常用,如我们会为了获取 ApplicationContext 而 implement ApplicationContextAware
// 注意:它不仅仅回调 ApplicationContextAware,
// 还会负责回调 EnvironmentAware、ResourceLoaderAware 等,看下源码就清楚了
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 下面几行的意思就是,如果某个 bean 依赖于以下几个接口的实现类,在自动装配的时候忽略它们,
// Spring 会通过其他方式来处理这些依赖。
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.
/**
* 下面几行就是为特殊的几个 bean 赋值,如果有 bean 依赖了以下几个,会注入这边相应的值,
* 之前我们说过,"当前 ApplicationContext 持有一个 BeanFactory",这里解释了第一行。
* ApplicationContext 还继承了 ResourceLoader、ApplicationEventPublisher、MessageSource
* 所以对于这几个依赖,可以赋值为 this,注意 this 是一个 ApplicationContext
* 那这里怎么没看到为 MessageSource 赋值呢?那是因为 MessageSource 被注册成为了一个普通的 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.
// 这个 BeanPostProcessor 也很简单,在 bean 实例化后,如果是 ApplicationListener 的子类,
// 那么将其添加到 listener 列表中,可以理解成:注册 事件监听器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
// 这里涉及到特殊的 bean,名为:loadTimeWeaver,这不是我们的重点,忽略它
// tips: ltw 是 AspectJ 的概念,指的是在运行期进行织入,这个和 Spring AOP 不一样,
// 感兴趣的读者请参考我写的关于 AspectJ 的另一篇文章 https://www.javadoop.com/post/aspectj
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()));
}
/**
* 从下面几行代码我们可以知道,Spring 往往很 "智能" 就是因为它会帮我们默认注册一些有用的 bean,
* 我们也可以选择覆盖
*/
// Register default environment beans.
// 如果没有定义 "environment" 这个 bean,那么 Spring 会 "手动" 注册一个
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
// 如果没有定义 "systemProperties" 这个 bean,那么 Spring 会 "手动" 注册一个
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
// 如果没有定义 "systemEnvironment" 这个 bean,那么 Spring 会 "手动" 注册一个
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
接下来我们开始进入到finishBeanFactoryInitialization这个方法,关于前面的几个方法这边再贴一下
// 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
// 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了,不然没完没了了
initMessageSource();
// Initialize event multicaster for this context.
// 初始化当前 ApplicationContext 的事件广播器,这里也不展开了
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 从方法名就可以知道,典型的模板方法(钩子方法),
// 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
onRefresh();
// Check for listener beans and register them.
// 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,直接过
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 初始化所有的 singleton beans
//(lazy-init 的除外)
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 最后,广播事件,ApplicationContext 初始化完成
finishRefresh();
进入到本次IOC源码的高潮部分了,请大家系好安全带,即将发车…
进入AbstractApplicationContext的finishBeanFactoryInitialization方法
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 首先,初始化名字为 conversionService 的 Bean。
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));
}
// 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));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 这是 AspectJ 相关的内容,放心跳过吧
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
// 到这一步的时候,Spring 已经开始预初始化 singleton beans 了,
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 看这里 开始初始化
beanFactory.preInstantiateSingletons();
}
进入preInstantiateSingletons方法,拿到刚刚beanFactory注册BeanDefinition的名字集合,遍历,可能存在继承关系,如果有则合并,然后判断bean是否是抽象的单例的,懒加载的,满足要求然后再判断该bean是否是个FactoryBean,isFactoryBean方法主要还是通过instanceof来判断的,前面那道面试题我们已经讲了FactoryBean和普通Bean的区别,取得话就在于beanName前面有无"&"
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
// this.beanDefinitionNames 保存了所有的 beanNames
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
// 下面这个循环,触发所有的非懒加载的 singleton beans 的初始化操作
for (String beanName : beanNames) {
// 合并父 Bean 中的配置,注意 中的 parent,用的不多吧,
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 非抽象、非懒加载的 singletons。如果配置了 'abstract = true',那是不需要初始化的
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
// 处理 FactoryBean
// FactoryBean 的话,在 beanName 前面加上 ‘&’ 符号。再调用 getBean,getBean 方法别急
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
// 判断当前 FactoryBean 是否是 SmartFactoryBean 的实现,此处忽略,直接跳过
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) 这个方法就可以进行初始化了
//看这里!!!!!!!!
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
// 到这里说明所有的非懒加载的 singleton beans 已经完成了初始化
// 如果我们定义的 bean 是实现了 SmartInitializingSingleton 接口的,那么在这里得到回调,忽略
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
AbstractBeanFactory.java
来到了getBean方法
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
doGetBean 注意 有2个getSingleton,3个getObjectForBeanInstance,这块一定要逐个分析一下
//告诉编译器忽略 unchecked 警告信息,如使用List,ArrayList等未进行参数化产生的警告信息。
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//1.转换对应的beanName
// 获取一个 “正统的” beanName,处理两种情况,一个是前面说的 FactoryBean(前面带 ‘&’),
// 一个是别名问题,因为这个方法是 getBean,获取 Bean 用的,你要是传一个别名进来,是完全可以的
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//2.直接尝试从缓存获取或者 singleton Factories 巾的 Object Factory 获垠
// 这里说下 args 呗,虽然看上去一点不重要。前面我们一路进来的时候都是 getBean(beanName),
// 所以 args 传参其实是 null 的,但是如果 args 不为空的时候,那么意味着调用方不是希望获取 Bean,而是创建 Bean
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
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 + "'");
}
}
//3.如果从缓存中得到了bean的原始状态,则对bean进行实例化
// 下面这个方法:如果是普通 Bean 的话,直接返回 sharedInstance,
// 如果是 FactoryBean 的话,返回它创建的那个实例对象
// (FactoryBean 知识,读者若不清楚请移步附录)
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
/**
* 只有在单例的情况才会尝试解决循环依赖,原型模式情况下,如果存在
* A 中有B的属性,那么当依赖注入的时候,就会产生当且还未创建完的时候因为
* 对于B 创边再次返回创建A ,造成循环依赖, 也就是下面的情况
*/
//4.原型模式的依赖检查
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
//检查一下这个BeanDefinition 在容器中是否存在
BeanFactory parentBeanFactory = getParentBeanFactory();
//如果beanDefinitionMap中也就是在所有已经加载的类中不包括beanName则尝试从parentBeanFactory中检测
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
//递归到beanFactory中寻找
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// Delegation to parent with explicit args.
//委派父级容器根据指定名称和显式的参数查找
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else {
// No args -> delegate to standard getBean method.
//委派父级容器根据指定名称和类型查找
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
//如果不是仅仅做类型检查则是创建bean,这里要进行记录
if (!typeCheckOnly) {
// typeCheckOnly 为 false,将当前 beanName 放入一个 alreadyCreated 的 Set 集合中。向容器标记指定的Bean已经被创建
markBeanAsCreated(beanName);
}
/*
* 稍稍总结一下:
* 到这里的话,要准备创建 Bean 了,对于 singleton 的 Bean 来说,容器中还没创建过此 Bean;
* 对于 prototype 的 Bean 来说,本来就是要创建一个新的 Bean。
*/
try {
//将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition,如果指定BeanName是子Bean的话同时会合并父类的相关属性
//主要解决Bean继承时子类合并父类公共属性问题
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 先初始化依赖的所有 Bean,这个很好理解。
// 注意,这里的依赖指的是 depends-on 中定义的依赖
String[] dependsOn = mbd.getDependsOn();
//若存在依赖则需要递归实例化依赖的bean
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);
try {
//递归调用getBean()方法,先初始化被依赖项
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
// 如果是 singleton scope 的,创建 singleton 的实例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
//执行创建 Bean , 详解后面再说
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
//多例模式的创建
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
// 执行创建 Bean
prototypeInstance = createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
//如果不是 singleton 和 Prototype 的话,需要委托给相应的实现类来处理
//指定的scope创建bean
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
// 执行创建 Bean
return createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
} catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
// 最后,检查一下类型对不对,不对的话就抛异常,对的话就返回了
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
} catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
第一个getSingleton
然后到getSingleton方法,注意allowEarlyReference为true表示Spring默认是支持循环依赖的,这段逻辑到第一个判断就直接返回了,原因在于isSingletonCurrentlyInCreation方法,点进去就是判断这个beanName是否在这个Set中,不满足直接返回了Null
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
//然后到getSingleton方法,注意allowEarlyReference为true表示Spring默认是支持循环依赖的
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 第一次进来this.singletonObjects.get(beanName)返回的肯定是null。然后isSingletonCurrentlyInCreation决定了能否进入二级缓存中获取数据。
synchronized (this.singletonObjects) {
//从二级缓存获取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//调用预先设定的getObject()方法
singletonObject = singletonFactory.getObject();
//记录在缓存中,earlySingletonObjects和singletonFactories互斥
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
然后因为sharedInstance为空所以if不满足走else,然后到了这一步,对原型的检查
//4.原型模式的依赖检查
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//如何判断的,这里涉及到一个ThreadLocal的概念,目前为空,
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
return (curVal != null &&
(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}
然后就是一系列判断,拿到我们前面注册到bean工厂的BeanDefinition对象,也就是这里的RootBeanDefinition,判断他是单例的还是多例的还是其他的,然后走各自对应的处理逻辑,目前我们的beanName为messageService,默认单例,所以我们又到了看第二个getSingleton方法。
对于下面这段代码,有个lambda表达式,也许有的老铁就慌了,莫慌莫慌。调试一下…
// 如果是 singleton scope 的,创建 singleton 的实例
if (mbd.isSingleton()) {
//看这里
sharedInstance = getSingleton(beanName, () -> {
try {
//执行创建 Bean , 详解后面再说
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) { ...}
断点调试首先进来getSingleton方法,仔细看图类名+$lambda,这是什么鬼????
然后我们看下ObjectFactory,代码如下:
@FunctionalInterface
public interface ObjectFactory<T> {
/**
* Return an instance (possibly shared or independent)
* of the object managed by this factory.
* @return the resulting instance
* @throws BeansException in case of creation errors
*/
//返回一个由此工厂管理的实例,
T getObject() throws BeansException;
}
然后这个lambda表达式是在调用getObject()方法的时候触发的,小伙伴们可以自己断点试试,这也算一个亮眼的操作了…继续讲解getSingleton方法
前面我们在if(isSingletonCurrentlyInCreation)有个判断,如果成立则会抛出循环依赖的异常信息,
到这个getSingleton方法里的beforeSingletonCreation方法才是往singletonsCurrentlyInCreation添加当前的beanName。
然后就是调用singletonFactory.getObject();也就是AbstractBeanFactory的getSingleton的lambda,这块一定要注意。
到了finally的afterSingletonCreation方法,就把singletonsCurrentlyInCreation的beanName给拿掉
如果lambda执行没问题newSingleton赋值为true,然后执行addSingleton方法。
到这里,单例bean的外部逻辑我们已经锊清楚了。
下面是getSingleton方法和里面几个重要方法的代码。
//因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,
// Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦
//下一个bean创建时需要依赖上个bean,则直接使用ObjectFactory.
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
//断言beanName肯定不为空
Assert.notNull(beanName, "Bean name must not be null");
//同步全局变量,开始创建单例
synchronized (this.singletonObjects) {
//查看单例是否已经被加载,凡是加载过的单例,都会存在Map singletonObjects里面
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//this.singletonsCurrentlyInDestruction是个boolean,记录的是当前这个单例是否正在被销毁,
//如果是true,代表单例已经执行了自身的destroy销毁方法,或者有异常的时候执行了destroySingleton方法等情况
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//从一级缓存中取肯定为NULL,这里往singletonsCurrentlyInCreation添加beanName
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
//如果此时suppressedExceptions为空,就new LinkedHashSet<>()来保存接下来可能发生的异常
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//到这里就会调用外面的lambda表达式
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
//如果没有创建报错
if (singletonObject == null) {
throw ex;
}
} catch (BeanCreationException ex) {
//把出现过的异常加进去
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//后处理,主要是把刚刚在beforeSingletonCreation方法里面加载的bean状态删除
afterSingletonCreation(beanName);
}
if (newSingleton) {
//把结果存在缓存中,并删除一些中间状态
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
beforeSingletonCreation方法
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
然后finally的afterSingletonCreation方法
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
addSingleton方法
if (newSingleton) {
//把结果存在缓存中,并删除一些中间状态
addSingleton(beanName, singletonObject);
}
也就是执行我们的lambda内容,IOC核心部分要来了
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//要注意,在我们的初始化阶段,args 是 null。
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
// 确保 BeanDefinition 中的 Class 被加载
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
// 准备方法覆写,这里又涉及到一个概念:MethodOverrides,它来自于 bean 定义中的
// 和 ,如果读者感兴趣,回到 bean 解析的地方看看对这两个标签的解析。
// 我在附录中也对这两个标签的相关知识点进行了介绍,读者可以移步去看看
try {
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 让 InstantiationAwareBeanPostProcessor 在这一步有机会返回代理,
// 在 《Spring AOP 源码分析》那篇文章中有解释,这里先跳过
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
} catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 看这里创建 bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
} catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
} catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
进入doCreateBean方法,1,2,3为其中的重点
//标记1,2,3是doCreateBean方法中3个比较重要的点
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 1.说明不是 FactoryBean,这里实例化 Bean,这里非常关键,细节之后再说
//根据指定Bean使用对应的策略创建Bean实例:如工厂方法,构造函数自动注入,简单初始化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 这个就是 Bean 里面的 我们定义的类 的实例,很多地方我直接描述成 "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));
//允许提前暴露,添加到三级缓存中
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//添加到三级缓存中
//对bean再一次依赖引用。主要应用于SmartInstantiationAwareBeanPostProcessor
//其中我们熟知的AOP的advice就是在这里动态织入到bean中...若没有则直接返回bean
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 2.这一步也是非常关键的,这一步负责属性装配,因为前面的实例只是实例化了,并没有设值,这里就是设值
populateBean(beanName, mbd, instanceWrapper);
// 还记得 init-method 吗?还有 InitializingBean 接口?还有 BeanPostProcessor 接口?
// 3.这里就是处理 bean 初始化完成后的各种回调
exposedObject = initializeBean(beanName, exposedObject, mbd);
} catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
} else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
//如果是A和B存在循环依赖关系,在B的生命周期调用完了后置处理器之后到这,因传入false,导致为空,为什么要传入false,是因为A此时已经完了后置处理器,但A这个Bean
//其实没有创建完,如果还想生成代理类,是有问题的,这也就是为什么spring二级缓存不用,选择三级缓存的原因
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
} catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
推断构造方法
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
// 确保已经加载了此 class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 校验一下这个类的访问权限
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//如果工厂方法不为空则使用工厂方法初始化策略,其实也对是对应xml的标签
if (mbd.getFactoryMethodName() != null) {
// 采用工厂方法实例化,不熟悉这个概念的读者请看附录,注意,不是 FactoryBean
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
// 如果不是第一次创建,比如第二次创建 prototype bean。
// 这种情况下,我们可以从第一次创建知道,采用无参构造函数,还是构造函数依赖注入 来完成实例化
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);
}
}
// Candidate constructors for autowiring?
// 判断是否采用有参构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 构造函数依赖注入
return autowireConstructor(beanName, mbd, ctors, args);
}
// No special handling: simply use no-arg constructor.
// 调用无参构造函数
return instantiateBean(beanName, mbd);
}
本次我们调用的是无参构造方法,所以进入到instantiateBean,可以看到Spring将实例化的bean封装成了一个BeanWrapper的包装类
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
getInstantiationStrategy().instantiate(mbd, beanName, parent),
getAccessControlContext());
} else {
// 调用初始化策略
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
// 包装一下,返回
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
} catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
进入到Bean初始化策略的instantiate方法,大体逻辑我们分析一下
1.判断bd存不存在方法覆写,默认没有,所以进if,他先回去尝试一下能不能拿到我们要用的构造,也就是定义的constructorToUse,正常情况下没配置都是拿不到,所以为NULL,再进去,通过bd拿到我们的Class,看到这里,是不是就是我们java的反射知识了,继续看,他会判断这个class是不是一个接口,如果是就是抛出RuntimeException类型异常。顺便再提一点,我们工作中,关于service层,注意是service层的接口哈,为什么接口不用加注解,而在结尾为Impl的实现类加了注解@Service的原因,所以看源码对平常工作还是有一定帮助的。
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
// 如果不存在方法覆写,那就使用 java 反射进行实例化,否则使用 CGLIB,这里就是判断采用什么初始化bean的策略
// 方法覆写 eg: lookup-method 和 replaced-method
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
//默认构造方法
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
// 利用构造方法进行实例化
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
// 存在方法覆写,利用 CGLIB 来完成实例化,需要依赖于 CGLIB 生成子类
// 因为如果不使用 CGLIB 的话,存在 override 的情况 JDK 并没有提供相应的实例化支持
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
上面通过反射拿到我们的构造,接下来传入到一个BeanUtils的工具类进行实例化
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
//主要判断构造的修饰符,是不是能访问,如果是私有的,或者不能访问,那么我们就需要进行暴力访问
//也就是加上这行代码 ctor.setAccessible(true);
ReflectionUtils.makeAccessible(ctor);
//调用初始化策略,目前默认是newInstance来实例化的
return (KotlinDetector.isKotlinType(ctor.getDeclaringClass()) ?
KotlinDelegate.instantiateClass(ctor, args) : ctor.newInstance(args));
}
catch (InstantiationException ex) {
throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
}
catch (InvocationTargetException ex) {
throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
}
}
这个时候我们控制台打印了一句话,通过这个打印我们能清楚的知道这个通过构造进行实例化的
实例化Bean讲完了,下面这段代码很重要,设及到Spring比较难的知识点:循环依赖
下面这块代码是为了解决循环依赖的问题,earlySingletonExposure正常情况下都是true的,isSingletonCurrentlyInCreation(beanName),还记得前面一个方法叫beforeSingletonCreation这个么,我们这里还没有到afterSingletonCreation方法呢,还在lambda表达式里的getObject()方法实例化Bean呢,小伙伴们可千万别懵了。
然后到addSingletonFactory方法,这里又传了一个lambda,道理跟咋们前面讲的一样,
//是否需要提前曝光,判断条件为:单例&允许循环依赖&是否正在创建过程中
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
//允许提前暴露,添加到三级缓存中
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//添加到三级缓存中
//对bean再一次依赖引用。主要应用于SmartInstantiationAwareBeanPostProcessor
//其中我们熟知的AOP的advice就是在这里动态织入到bean中...若没有则直接返回bean
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
addSingletonFactory方法
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
//一级缓存不存在
if (!this.singletonObjects.containsKey(beanName)) {
//放入三级缓存中
this.singletonFactories.put(beanName, singletonFactory);
//移除二技缓存
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
Q:这里设及到Spring三级缓存方面的问题,由于本篇文章篇幅确实过长了,所以后期考虑开一篇文章来重点讲讲循环依赖,以及Spring为什么要使用三级缓存来解决该问题的?
继续第二步,DI部分
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
} else {
// Skip property population phase for null instance.
//没有需要填充的属性
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
// 1.InstantiationAwareBeanPostProcessor 处理器的postProcessAfterInstantiation函数的应用,此函数可以控制程序是否继续进行属性填充
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
// bean 实例的所有属性都在这里了
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 2. 根据注入类型,提取依赖的bean,并统一存入PropertyValues中
//没配置的话默认为0 关于名字,类型,构造分别对应1,2,3
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
// 通过名字找到所有属性值,如果是 bean 依赖,先初始化依赖的 bean。记录依赖关系
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
// 通过类型装配。复杂一些
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
//后处理器已经初始化
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
//需要依赖检查
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
// 3. 应用InstantiationAwareBeanPostProcessor处理器的postProcessPropertyValues方法,对属性获取完毕填充前对属性再次处理
//典型应用是RequiredAnnotationBeanPostProcessor类中对属性的验证
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 这里有个非常有用的 BeanPostProcessor 进到这里: AutowiredAnnotationBeanPostProcessor
// 对采用 @Autowired、@Value 注解的依赖进行设值,这里的内容也是非常丰富的,不过本文不会展开说了,感兴趣的读者请自行研究
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 4. 将PropertyValues属性填充到BeanWrapper中
if (pvs != null) {
// 设置 bean 实例的属性值 看这里
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
进入到第四步,前面主要是一些条件判断,然后拿到属性名字,原始值,这个原始值可能还不是我们要使用的,需要再处理一下,于是,下一步…
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs.isEmpty()) {
return;
}
if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
//如果mpvs中的值已经被转换为对应的类型那么可以直接设值到bw中
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
bw.setPropertyValues(mpvs);
return;
} catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
//如果 pvs 并不是使用 MutablePropertyValues 封装的类型,那么直接使用原始的属性获取方法
original = mpvs.getPropertyValueList();
} else {
original = Arrays.asList(pvs.getPropertyValues());
}
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
//获取对应·的解析器
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// Create a deep copy, resolving any references for values.
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
//遍历属性,将属性转换为对应类的对应属性的类型
for (PropertyValue pv : original) {
if (pv.isConverted()) {
deepCopy.add(pv);
} else {
String propertyName = pv.getName();
//原始的属性值,即转换之前的属性值
Object originalValue = pv.getValue();
//做一些类型的强制转换
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
//转换之后的属性值
Object convertedValue = resolvedValue;
//属性值是否可以转换
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
} else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
} else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}
// Set our (possibly massaged) deep copy.
try {
// AbstractPropertyAccessor
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
} catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
进入BeanDefinitionValueResolver的resolveValueIfNecessary方法
判断value是不是运行时Bean的引用,显然这里是,进入第一个return方法
@Nullable
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
// We must check each value to see whether it requires a runtime reference
// to another bean to be resolved.
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(argName, ref);
}
else if (value instanceof RuntimeBeanNameReference) {
String refName = ((RuntimeBeanNameReference) value).getBeanName();
refName = String.valueOf(doEvaluate(refName));
if (!this.beanFactory.containsBean(refName)) {
throw new BeanDefinitionStoreException(
"Invalid bean name '" + refName + "' in bean reference for " + argName);
}
return refName;
}
else if (value instanceof BeanDefinitionHolder) {
// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
}
else if (value instanceof BeanDefinition) {
// Resolve plain BeanDefinition, without contained name: use dummy name.
BeanDefinition bd = (BeanDefinition) value;
String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
ObjectUtils.getIdentityHexString(bd);
return resolveInnerBean(argName, innerBeanName, bd);
}
else if (value instanceof ManagedArray) {
// May need to resolve contained runtime references.
ManagedArray array = (ManagedArray) value;
Class<?> elementType = array.resolvedElementType;
if (elementType == null) {
String elementTypeName = array.getElementTypeName();
if (StringUtils.hasText(elementTypeName)) {
try {
elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
array.resolvedElementType = elementType;
}
catch (Throwable ex) {
// Improve the message by showing the context.
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error resolving array type for " + argName, ex);
}
}
else {
elementType = Object.class;
}
}
return resolveManagedArray(argName, (List<?>) value, elementType);
}
else if (value instanceof ManagedList) {
// May need to resolve contained runtime references.
return resolveManagedList(argName, (List<?>) value);
}
else if (value instanceof ManagedSet) {
// May need to resolve contained runtime references.
return resolveManagedSet(argName, (Set<?>) value);
}
else if (value instanceof ManagedMap) {
// May need to resolve contained runtime references.
return resolveManagedMap(argName, (Map<?, ?>) value);
}
else if (value instanceof ManagedProperties) {
Properties original = (Properties) value;
Properties copy = new Properties();
original.forEach((propKey, propValue) -> {
if (propKey instanceof TypedStringValue) {
propKey = evaluate((TypedStringValue) propKey);
}
if (propValue instanceof TypedStringValue) {
propValue = evaluate((TypedStringValue) propValue);
}
if (propKey == null || propValue == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error converting Properties key/value pair for " + argName + ": resolved to null");
}
copy.put(propKey, propValue);
});
return copy;
}
else if (value instanceof TypedStringValue) {
// Convert value to target type here.
TypedStringValue typedStringValue = (TypedStringValue) value;
Object valueObject = evaluate(typedStringValue);
try {
Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
if (resolvedTargetType != null) {
return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
}
else {
return valueObject;
}
}
catch (Throwable ex) {
// Improve the message by showing the context.
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error converting typed String value for " + argName, ex);
}
}
else if (value instanceof NullBean) {
return null;
}
else {
return evaluate(value);
}
}
看到这里,不知道小伙伴是明白了还是懵了,哈哈,我们说说这断代码:拿到beanName,然后判断,又是一个beanFactory,没错,这就是我们前面得到的DefaultListableBeanFactory,IOC的始祖
@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
Object bean;
String refName = ref.getBeanName();
refName = String.valueOf(doEvaluate(refName));
if (ref.isToParent()) {
if (this.beanFactory.getParentBeanFactory() == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Can't resolve reference to bean '" + refName +
"' in parent factory: no parent factory available");
}
bean = this.beanFactory.getParentBeanFactory().getBean(refName);
}
else {
//-----------------------------看这里------------------------------------------
bean = this.beanFactory.getBean(refName);
this.beanFactory.registerDependentBean(refName, this.beanName);
}
if (bean instanceof NullBean) {
bean = null;
}
return bean;
}
catch (BeansException ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
}
}
进入getBean方法
又到了我们最初的messageService的起点了,不过这次是beanName为message的bean
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
这是我们开始的xml配置
<bean id="messageService" name="m1,m2,m3" scope="singleton" class="com.whp.service.impl.MessageServiceImpl">
<!--引入下面id为message的bean-->
<property name="message" ref="message"/>
</bean>
<bean id="message" class="com.whp.bean.Message"/>
然后重复messageService之后,我们拿到了beanName为message的bean,这时候需要给MessageServiceImpl这个类的属性message赋值了,还是我们前面的DI的过程,然后接下来就是赋值了。
前面2步我们已经把Bean实例化以及DI完成了,最后就是回调以及通知了,工作亦是如此…
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//JDK的安全机制验证权限
if (System.getSecurityManager() != null) {
//实现PrivilegedAction接口的匿名内部类
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
} else {
// 如果 bean 实现了 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 接口,回调
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor 的 postProcessBeforeInitialization 回调
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 处理 bean 中定义的 init-method,
// 或者如果 bean 实现了 InitializingBean 接口,调用 afterPropertiesSet() 方法
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 回调
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
部分Aware回调
进入invokeAwareMethods方法,这部分我们叫做部分Aware回调,这里就三个,对于Aware接口的实现肯定有多个,所以这里我们叫部分Aware接口回调
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
还记得嘛,我开始在MessageServiceImpl实现了BeanNameAware,然后setBeanName方法,就是为了这一步
然后到了BeanPostProcessor的前后通知
applyBeanPostProcessorsBeforeInitialization方法
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
applyBeanPostProcessorsAfterInitialization方法
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
对于BeanPostProcessor,是Spring提供给我们开发者的一个非常重要的拓展点,还有FactoryBean
,InitializingBean我们也可以利用它来初始化我们自定义的一些Bean,Aware接口我们也可以利用起来
第3步完成过后有个if (earlySingletonExposure) {…}这块属于循坏依赖东西,后期有时间会开篇文章重点讲讲。
这个时候我们的beanName为messageService的Bean实例化完成了,最后需要把它放入到Spring的一级缓存中,供开发者使用。
afterSingletonCreation(beanName)将singletonsCurrentlyInCreation的beanName移除
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
addSingleton方法
//一句话,Bean添加到一级缓存,移除二三级缓存。
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//一级缓存添加
this.singletonObjects.put(beanName, singletonObject);
//移除三级,二级缓存
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
// registeredSingletons这个Set是记录已经创建好的bean
this.registeredSingletons.add(beanName);
}
}
最后一个就是getObjectForBeanInstance方法了
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
//执行创建 Bean , 详解后面再说
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
* 这个方法就三个判断:
* 1、如果不是factoryBean 但是name开头为&,那么报错
* 2、如果是FactoryBean,并且name开头不为&,就取FactoryBean的getObject方法
* 3、如果是FactoryBean,并且name开头为&,那么返回FactoryBean本身。
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
if (BeanFactoryUtils.isFactoryDereference(name)) {
//
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
//如果name开头&,但又不是factoryBean就报错
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
//如果不是FactoryBean,那么就属于正常的bean实例了,直接返回
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
//加载FactoryBean
Object object = null;
if (mbd == null) {
//尝试从缓存中获取bean
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
//强转为beanFactory。此时的beanInstance一定是FactoryBean类型的,因为如果不是,就会在上面的if中直接返回了
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
//检测这个bean是否已经被加载过
//containsBeanDefinition中会返回beanDefinitionMap.containsKey(beanName)的值
if (mbd == null && containsBeanDefinition(beanName)) {
//进行父类和子类的合并,把存储xml配置的GernericBeanDefinition转换为RootBeanDefinition
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
//我的bean是FactoryBean,那么就会通过FactoryBean的getObject方法
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
到这里,可以说是Spring初始化完成了,我们可以通过一下进行调用使用了
MessageService messageService = (MessageService) applicationContext.getBean("messageService");
本次的Spring IOC源码解析已接近了尾声,不知道有多少小伙伴坚持看完了,看完的可以在下方回复Spring IOC,也表示对博主写了这么久的认可哈哈,确实有点辛苦,如果本篇文章有缺点,欢迎指教,需要源码项目的也可以找我要,省的大家去下载了,本次Spring IOC源码解析到此结束。