Spring IOC源码分析笔记
IOC 总体来说有两处地方最重要,一个是创建 Bean 容器,一个是初始化 Bean.
1. 最基本的Spring启动
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:application.xml");
}
只需要简单的加载classpath下的application.properties配置文件就可以启动.
需要在pom文件里添加spring依赖.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
spring-context 会自动将 spring-core、spring-beans、spring-aop、spring-expression 这几个基础 jar 包带进来。
2. ApplicationContext的继承结构和其他IOC容器实现类
偷一张ApplicationContext的继承结构:
在最下层的实现类还有FileSystemXmlApplicationContext和AnnotationConfigApplicationContext
1、FileSystemXmlApplicationContext 的构造函数需要一个 xml 配置文件在系统中的路径,其他和 ClassPathXmlApplicationContext 基本上一样。
2、AnnotationConfigApplicationContext 是基于注解来使用的,它不需要配置文件,采用 java 配置类和各种注解来配置,是比较简单的方式,也是大势所趋吧。
3. 一个QuickStart
1) 创建一个接口和他的实现类:
public interface MessageService {
String getMessage();
}
public class MessageServiceImpl implements MessageService {
public String getMessage() {
return "hello world";
}
}
2) 接下来, 在resources目录下新建一个xml配置文件.
名称随意,一般习惯叫application.xml 或 application-xxx.xml.
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName">
<bean id="messageService" class="com.echi.service.MessageServiceImpl"/>
</beans>
3) 在IOC容器实例完成之后, 从容器中获取bean
public class ApplicationStarter {
public static void main(String[] args) {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("classpath:application.xml");
System.out.println("context 启动成功");
// 从IOC容器中获取类型为MessageService的bean
MessageService messageService = applicationContext.getBean(MessageService.class);
// 调动bean的方法,确认实例成功
// 输出 hello world
System.out.println(messageService.getMessage());
}
}
这样就引出了主题, 为什么我们可以通过配置的方式就获取到bean.
ApplicationContext 启动过程中,会负责创建实例 Bean,往各个 Bean 中注入依赖等。
4. BeanFactory简介
BeanFactory就是一个生产bean的工厂, 它负责生产和管理各个bean的实例.
1) BeanFactory主要继承结构
ApplicationContext其实就是一个BeanFactory,
大概翻一下 BeanFactory , ListableBeanFactory , HierarchicalBeanFactory , AuthwireCapableBeanFactory , ApplicationContext 这几个接口的代码.
- BeanFactory中的方法大多都是getBean().
- ListableBeanFactory中有返回Map的getBean方法, 这个 Listable 的意思就是,通过这个接口,我们可以获取多个 Bean
- HierarchicalBeanFactory 内容比较少, 有一个getParentBeanFactory()方法, 也就是说会有父容器和子容器关系.
- AutowireCapableBeanFactory 比较眼熟autowire这个词, 里面有几个常量, AUTOWIRE_BY_NAME, BY_TYPE之类的, 就是用来自动装配bean的. 但是仔细看上面的继承图, ApplicationContext并没有继承他, 这个不要紧, 在ApplicationContext中有一个getAutowireCapableBeanFactory()方法,没有继承不代表不能组合使用.
- 还有一个ConfigurableListableBeanFactory , 继承了全部的三个BeanFactory接口.
2) 启动过程分析
先从ClasspathXMLApplicationContext的构造方法开始说起.
// 如果已经有 ApplicationContext 并需要配置成父子关系,那么调用这个构造方法
public ClassPathXmlApplicationContext(ApplicationContext parent) {
super(parent);
}
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations,
boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);
// 根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割)
setConfigLocations(configLocations);
if (refresh) {
// 核心方法
refresh();
}
}
接下来就是refresh()方法
这里简单说下为什么是 refresh(),而不是 init() 这种名字的方法。因为 ApplicationContext 建立起来以后,其实我们是可以通过调用 refresh() 这个方法重建的,refresh() 会将原来的 ApplicationContext 销毁,然后再重新执行一次初始化操作。
@Override
public void refresh() throws BeansException, IllegalStateException {
// 来个锁,不然 refresh() 还没结束,你又来个启动或销毁容器的操作,那不就乱套了嘛
synchronized (this.startupShutdownMonitor) {
// 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
prepareRefresh();
// 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
// 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
// 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
// 这块待会会展开说
prepareBeanFactory(beanFactory);
try {
// 【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
// 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】
// 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
// 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
postProcessBeanFactory(beanFactory);
// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
registerBeanPostProcessors(beanFactory);
// 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了,不然没完没了了
initMessageSource();
// 初始化当前 ApplicationContext 的事件广播器,这里也不展开了
initApplicationEventMulticaster();
// 从方法名就可以知道,典型的模板方法(钩子方法),
// 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
onRefresh();
// 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,过
registerListeners();
// 重点,重点,重点
// 初始化所有的 singleton beans
//(lazy-init 的除外)
finishBeanFactoryInitialization(beanFactory);
// 最后,广播事件,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);
// 把异常往外抛
throw ex;
}
finally {
resetCommonCaches();
}
}
}
下面,开始一步步肢解这个 refresh()
方法。
创建 Bean 容器前的准备工作
这个比较简单,直接看代码中的几个注释即可。
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();
// 校验 xml 配置文件
getEnvironment().validateRequiredProperties();
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
创建Bean容器,加载并注册Bean
回到refresh()
方法的下一行, obtainFreshBeanFactory()
这个方法是全文最重要的方法之一, 这里会初始化beanFactory, 加载Bean, 注册Bean等等.
当然,这步之后, bean并没有完成初始化.
// AbstractApplicationContext.java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 关闭旧的beanFactory(如果有), 创建新的beanFactory, 加载bean定义, 注册bean等...
refreshBeanFactory();
// 返回刚刚创建的beanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
// AbstractRefreshableApplicationContext.java 120
@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());
// 下面两个方法很重要
// 设置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);
}
}
ApplicationContext继承自BeanFactory, 但他不应该被理解为BeanFactory的实现类, 而是其内部有一个实例化的BeanFactory(
DefaultListableBeanFactory
). 以后所有的beanFactory操作其实是委托给这个实例处理的.
为什么选择实例化DefaultListableBeanFactory, 之前我们看BeanFactory继承结构图的时候,提到一个接口ConfigurableListableBeanFactory
, 他继承了BeanFactory下所有的接口, 而这个接口又有一个实现类 DefaultListableBeanFactory
, 这个实现类还继承了右边的AbstractAutowireCapableBeanFactory. 所以 DefaultListableBeanFactory
基本上是最牛的BeanFactory了,,这也是这边会使用这个类来实例化的原因。
如果你想要在程序运行的时候动态往 Spring IOC 容器注册新的 bean,就会使用到这个类。那我们怎么在运行时获得这个实例呢?
之前我们说过 ApplicationContext 接口能获取到 AutowireCapableBeanFactory,就是最右上角那个,然后它向下转型就能得到 DefaultListableBeanFactory 了。
在继续往下之前, 需要了解一个概念,BeanDefinition
. 我们说 BeanFactory 是 Bean 容器,那么 Bean 又是什么呢?
这里的BeanDefinition就是我们所说的Spring的Bean, 我们定义的各个Bean其实会转换成BeanDefinition存在于Spring的BeanFactory中.
所以, 如果有人问你Bean是什么的时候, 你要知道Bean在代码层面可以简单的认为是BeanDefinition的实例.
BeanDefinition中保存了我们的Bean信息, 比如这个Bean指向哪个类, 是否是单例, 是否懒加载, 这个Bean依赖了哪些Bean等..
BeanDefinition接口定义
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
// 我们可以看到, 默认只提供singleton和prototype两种.
// 那我们还知道request, session, globalSession, application 这几种呢?
// 他们属于基于 web 的扩展
String SCOPE_SINGLETON = "singleton";
String SCOPE_PROTOTYPE = "prototype";
// 不太重要
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
// 设置父Bean, 这里涉及到Bean的继承, 不是java继承.
// 一句话就是: 继承父Bean的配置信息
void setParentName(String var1);
// 获取父Bean
String getParentName();
// 设置Bean的类名称, 将来要通过反射来生成实例.
void setBeanClassName(String var1);
// 获取Bean的类名
String getBeanClassName();
// 设置Bean的scope
void setScope(String var1);
String getScope();
// 设置是否懒加载
void setLazyInit(boolean var1);
boolean isLazyInit();
// 设置Bean所依赖的所有Bean, 注意, 这里的依赖不是指属性依赖 (如 @Autowire标记的)
// 是 depends-on="" 属性设置的值
void setDependsOn(String... var1);
// 返回该bean的所有依赖
String[] getDependsOn();
// 设置该Bean是否可以注入到其他Bean中, 只对根据类型注入有效
// 如果根据名称注入, 即使这边设置false也是可以的.
void setAutowireCandidate(boolean var1);
// 该Bean是否可以注入到其他Bean中
boolean isAutowireCandidate();
// 主要的. 对于同一个接口的多个实现, 如果不指定名字的话,Spring会优先选择设置primary为true的bean
void setPrimary(boolean var1);
// 是否是primary的
boolean isPrimary();
// 如果该bean采用工厂方法生成, 指定工厂名称.
// 一句话的意思就是, 有些实例不是用反射创建的, 而是用工厂模式获取的.
void setFactoryBeanName(String var1);
// 获取工厂名称
String getFactoryBeanName();
// 指定工厂类中的 工厂方法名称
void setFactoryMethodName(String var1);
// 获取工厂类中的 工厂方法名称
String getFactoryMethodName();
// 构造器参数
ConstructorArgumentValues getConstructorArgumentValues();
// Bean中的属性值, 后面给Bean注入属性的时候会说到
MutablePropertyValues getPropertyValues();
// 是否singleton
boolean isSingleton();
// 是否prototype
boolean isPrototype();
// 如果这个Bean是被设置为abstract, 那么不能实例化.
// 常用作 父Bean 用于继承, 其实也很少用到
boolean isAbstract();
int getRole();
String getDescription();
String getResourceDescription();
BeanDefinition getOriginatingBeanDefinition();
}
这个 BeanDefinition 其实已经包含很多的信息了,暂时不清楚所有的方法对应什么东西没关系,希望看完本文后读者可以彻底搞清楚里面的所有东西。
这里接口虽然那么多,但是没有类似 getInstance() 这种方法来获取我们定义的类的实例,真正的我们定义的类生成的实例到哪里去了呢?别着急,这个要很后面才能讲到。
有了BeanDefinition的概念后, 我们继续往下看refreshBeanFactory中的内容.
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
虽然只有两个方法,但路还很长啊。。。
customizeBeanFactory
customizeBeanFactory(beanFactory)比较简单, 就是配置是否允许BeanDefinition覆盖,是否允许循环引用.
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
// 是否允许Bean定义覆盖
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
// 是否允许Bean间循环引用
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
BeanDefinition覆盖的问题可能好多开发者会碰到这个坑, 就是在配置文件中定义bean的时候,使用了相同的id或name, 默认情况下, allowBeanDefinitionOverriding属性为null, 如果同一配置文件中重复了, 会抛错, 但是如果不是同一配置文件中, 会发生覆盖.
循环引用也很好理解: A依赖B, B依赖A. 或A依赖B, B依赖C, C依赖A.
默认情况下, Spring允许依赖循环, 当然如果你在A的构造器中依赖B, B的构造器中依赖A是不行的.
加载Bean: loadBeanDefinitions
接下来是最重要的loadBeanDefinition(beanFactory)方法了, 这个方法将根据配置, 加载各个Bean, 然后放入BeanFactory中.
读取配置的操作在XmlBeanDefinitionReader中, 其负责加载配置, 解析.
// AbstractXmlApplicationContext.java 80
/** 我们可以看到,此方法将通过一个 XmlBeanDefinitionReader 实例来加载各个 Bean。*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
throws BeansException, IOException {
// 给这个BeanFactory实例化一个XmlBeanDefinitionReader
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));
// 初始化BeanDefinitionReader, 其实是提供给子类覆写的.
// 我看了一下,没有类覆写这个方法,我们姑且当做不重要吧
initBeanDefinitionReader(beanDefinitionReader);
// 重点来了,继续往下
loadBeanDefinitions(beanDefinitionReader);
}
接下来用刚刚实例化的XMLBeanDefinitionReader来加载Xml配置,
// AbstractXmlApplicationContext.java 120
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader)
throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
// 进入
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
// 2
reader.loadBeanDefinitions(configLocations);
}
}
// 上面虽然有两个分支,不过第二个分支很快通过解析路径转换为 Resource 以后也会进到这里
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
// 这里是一个for循环, 也就是每一个文件是一个resource
for (Resource resource : resources) {
// 进入
counter += loadBeanDefinitions(resource);
}
//最后返回 counter,表示总共加载了多少的 BeanDefinition
return counter;
}
// XMLBeanDefinitionReader.java 302
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
// XMLBeanDefinitionReader.java 314
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.getResource());
}
// 用一个ThreadLocal来存放配置文件资源
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
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();
}
}
}
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 将xml转成Document对象
Document doc = doLoadDocument(inputSource, resource);
// 进入
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
...
}
public int registerBeanDefinitions(Document doc, Resource resource)
throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
// 进入
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
// 返回从当前配置文件加载了多少数量的 Bean
return getRegistry().getBeanDefinitionCount() - countBefore;
}
// DefaultBeanDefinitionDocumentReader.java 90
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
经过漫长的链路,一个配置文件终于转换为一颗 DOM 树了,注意,这里指的是其中一个配置文件,不是所有的,读者可以看到上面有个 for 循环的。下面开始从根节点开始解析:
// DefaultBeanDefinitionDocumentReader.java 116
protected void doRegisterBeanDefinitions(Element root) {
// BeanDefinitionParserDelegate 负责解析Bean定义
// 这里为什么要定义一个 parent? 看到后面就知道了,是递归问题,
// 因为 <beans /> 内部是可以定义 <beans /> 的,所以这个方法的 root 其实不一定就是 xml 的根节点,
// 也可以是嵌套在里面的 <beans /> 节点,从源码分析的角度,我们当做根节点就好了
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
// 这块说的是根节点 <bean ... profile="dev"> 中的profile是否是当前环境需要的
// 如果当前环境配置的profile不包含此profile, 就直接return了, 不对此<beans /> 解析.
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;
}
preProcessXml(root) 和 postProcessXml(root) 是给子类用的钩子方法,鉴于没有被使用到,也不是我们的重点,我们直接跳过。
这里涉及到了 profile 的问题,对于不了解的读者,我在附录中对 profile 做了简单的解释,读者可以参考一下。
profile就是多环境配置中, application-xxx.properties 中配置的环境.
即, 如果配置了 <bean .. profile=”dev” /> 那么只有在dev环境生效时, 才会加载这个bean
接下来,看核心解析方法 parseBeanDefinitions(root, this.delegate)
:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
// default namespace 涉及到的就四个标签 <import />、<alias />、<bean /> 和 <beans />,
// 其他的属于 custom 的
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)) {
// 解析default namespace下面的元素
parseDefaultElement(ele, delegate);
}
else {
// 解析其他 namespace 下面的元素
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
从上面的代码,我们可以看到,对于每个配置来说,分别进入到 parseDefaultElement(ele, delegate);
和 delegate.parseCustomElement(ele);
这两个分支了。
parseDefaultElement(ele, delegate);
解析的节点是 <import />
, <alias />
, <beans />
, <bean />
这几个.
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// 处理 <import />
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
// 处理<alias />
// <alias name="fromName" alias="toName"/>
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
// 处理 <bean /> ,这也算是我们的重点吧
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
// 处理 <beans />
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// 如果碰到的是嵌套的 <beans /> 标签,需要递归
doRegisterBeanDefinitions(ele);
}
}
我们重点说
processBeanDefinition 解析 bean 标签
// DefaultBeanDefinitionDocumentReader 298
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 将节点中的信息提取出来, 封装成一个BeanDefinitionHolder
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
// 下面几行先跳过
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
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));
}
}
继续往下看怎么解析之前,我们先看下
Property | |
---|---|
class | 类的全限定名 |
name | 可指定 id、name(用逗号、分号、空格分隔) |
scope | 作用域 |
constructor arguments | 指定构造参数 |
properties | 设置属性的值 |
autowiring mode | no(默认值)、byName、byType、 constructor |
lazy-initialization mode | 是否懒加载(如果被非懒加载的bean依赖了那么其实也就不能懒加载了) |
initialization method | bean 属性设置完成后,会调用这个方法 |
destruction method | bean 销毁后的回调方法 |
简单地说就是像下面这样子:
<bean id="exampleBean" name="name1, name2, name3" class="com.javadoop.ExampleBean"
scope="singleton" lazy-init="true" init-method="init" destroy-method="cleanup">
<!-- 可以用下面三种形式指定构造参数 -->
<constructor-arg type="int" value="7500000"/>
<constructor-arg name="years" value="7500000"/>
<constructor-arg index="0" value="7500000"/>
<!-- property 的几种情况 -->
<property name="beanOne">
<ref bean="anotherExampleBean"/>
</property>
<property name="beanTwo" ref="yetAnotherBean"/>
<property name="integerProperty" value="1"/>
</bean>
当然,除了上面举例出来的这些,还有 factory-bean、factory-method、
有了以上这些知识以后,我们再继续往里看怎么解析 bean 元素,是怎么转换到 BeanDefinitionHolder 的。
// BeanDefinitionParserDelegate.java 428
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
// 将name属性的定义按照 "逗号,分好,空格"切分, 形成一个别名列表数组
// 如果没有定义name, 就为空.
List<String> aliases = new ArrayList<String>();
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);
}
// 根据 <bean ..>...</bean> 中的配置创建 BeanDefinition, 然后把配置中的信息都设置到实例中.
// 细节后面再说, 先知道这行过后就产生了一个BeanDefinition.
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
// 到这里, 整个<bean />标签就算解析结束了, 一个BeanDefinition也形成了.
if (beanDefinition != null) {
// 如果没有设置id和name的话, 就会进入下面这块代码
if (!StringUtils.hasText(beanName)) {
try {
// 按照我们的思路,这里 containingBean 是 null 的
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
// 如果我们不定义 id 和 name,那么我们引言里的那个例子:
// 1. beanName 为:com.javadoop.example.MessageServiceImpl#0
// 2. beanClassName 为:com.javadoop.example.MessageServiceImpl
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null && beanName.startsWith(beanClassName) &&
beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
// 把beanClassName设置成别名
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;
}
然后,我们再看看怎么根据配置创建 BeanDefinition 实例的:
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
try {
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
// 创建 BeanDefinition,然后设置类信息而已,很简单,就不贴代码了
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
// 设置 BeanDefinition 的一堆属性,这些属性定义在 AbstractBeanDefinition 中
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
// 解析 <meta />
parseMetaElements(ele, bd);
// 解析 <lookup-method />
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
// 解析 <replace-method />
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
// 解析 <cnostructor-arg />
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;
}
到这里, 我们已经根据
我们回到解析
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 上面一大串就是创建了BeanDefinitionHolder
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 如果有自定义属性的话, 先进行相关解析, 先忽略
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 我们把这一步叫做 注册Bean吧
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 注册完成后,发送事件,本文不展开说这个
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
我们已经根据
public class BeanDefinitionHolder implements BeanMetadataElement {
private final BeanDefinition beanDefinition;
private final String beanName;
private final String[] aliases;
}
然后我们准备注册这个BeanDefinition, 最后, 把这个注册时间发送出去
下面, 我们说说注册bean吧.
// BeanDefinitionReaderUtils
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
// 注册这个bean
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 如果有别名的话, 也要把别名注册一下, 不然根据别名找不到bean了
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
// alias -> beanName 保存它们的别名信息,这个很简单,用一个 map 保存一下就可以了,
// 获取的时候, 会将alias转成 beanName, 然后再查找
registry.registerAlias(beanName, alias);
}
}
}
别名注册先放一边,毕竟他很简单. 我们先看看怎么注册Bean
// DefaultListableBeanFactory.java 793
@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 {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// old? 还记得 “允许 bean 覆盖” 这个配置吗?allowBeanDefinitionOverriding
BeanDefinition oldBeanDefinition;
// 之后会看到, 所有的Bean注册后会放入到这个BeanDefinitionMap中
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
// 处理重复名称 bean定义的情况.
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
// 如果不允许覆盖的话, 抛异常
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// 用框架 的bean覆盖用户自定义的bean
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
// 用新的bean覆盖旧的bean
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
// 覆盖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<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// 正常应该是进入这个分支
// 将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 (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
总结一下, 到这里已经初始化了Bean容器,
一直到上面, 东西都还算简单, 只是比较繁琐.
bean容器实例化完成之后
说到这里, 我们回到refresh方法, 是的,我们才刚刚说完obtainFreshBeanFactory方法.
@Override
public void refresh() throws BeansException, IllegalStateException {
// 来个锁,不然 refresh() 还没结束,你又来个启动或销毁容器的操作,那不就乱套了嘛
synchronized (this.startupShutdownMonitor) {
// 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
prepareRefresh();
// 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
// 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
// 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
// 这块待会会展开说
prepareBeanFactory(beanFactory);
try {
// 【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
// 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】
// 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
// 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
postProcessBeanFactory(beanFactory);
// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 回调方法
invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。这里仅仅是注册,之后会看到回调这两方法的时机
registerBeanPostProcessors(beanFactory);
// 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了,不然没完没了了
initMessageSource();
// 初始化当前 ApplicationContext 的事件广播器,这里也不展开了
initApplicationEventMulticaster();
// 从方法名就可以知道,典型的模板方法(钩子方法),不展开说
// 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
onRefresh();
// 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,过
registerListeners();
// 重点,重点,重点
// 初始化所有的 singleton beans
//(lazy-init 的除外)
finishBeanFactoryInitialization(beanFactory);
// 最后,广播事件,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);
// 把异常往外抛
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
准备bean容器: prepareBeanFactory
之前我们说过, Spring把我们在xml配置的bean都注册之后,或”手动”注册一些特殊的bean.
这里简单介绍一下prepareBeanFactory(factory)方法.
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置beanFactory的类加载器, 我们知道beanFactory需要加载类, 也就需要类加载器
// 这里设置当前Application类的类加载器
beanFactory.setBeanClassLoader(getClassLoader());
// 设置BeanExpressResolver
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 添加了一个BeanPostProcessor, 这个processor比较简单:
// 实现了 Aware 接口的beans 在初始化的时候, 这个processor负责回调
// 这个我们很常用, 比如为了获取ApplicationContext而 implements 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);
// 下面几行就是为几个特殊的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);
// 这个BeanPostProcessor也很简单, 在Bean实例化之后, 如果是ApplicationListener的子类
// 那么将其添加到listener列表中, 可以理解为: 注册事件监听器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 这里涉及到的特殊bean, 名为 loadTimeWeaver, 这不是重点, 忽略他
// tips: ltw是AspectJ的概念, 指的是运行期进行织入, 和Spring的AOP不同
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
// 当然我们也可以选择覆盖
// 如果我们没有定义"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());
}
}
在上面这块代码中, Spring对一些特殊的bean做了处理, 暂时看不懂也没关系.
初始化所有的Singleton bean
我们的重点是 finishBeanFactoryInitialization(beanFactory);
这个方法, 这里会负责初始化所有的singleton bean
注意,在后面会用初始化
或预初始化
来代表这个阶段, Spring会在这个阶段完成所有Singleton bean的实例化.
我们先总结一下, 到目前为止, BeanFactory已经创建完成, 并且所有实现了BeanFactoryPostProcessor接口的bean已经初始化, 并且postProcessBeanFactory(factory)方法已经得到回调. 而且Spring也手动注册了一些特殊的Bean, 如 environment, systemProperties等.
剩下的就是初始化 singleton bean 了, 我们知道他是单例的, 如果没有懒加载, spring会在接下来初始化所有的singleton bean.
// AbstractApplicationContext.java 834
// 初始化所有剩余的singleton beans
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 首先, 初始化名字为 convertionService的bean, conversionService相关会贴在紧跟着这块代码后
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
//什么,看代码这里没有初始化 Bean 啊!
// 初始化的动作包装在 beanFactory.getBean()中, 这里先不说细节
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(new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
return getEnvironment().resolvePlaceholders(strVal);
}
});
}
// 先初始化所有 LoadTimeWeaver 类型的bean,
// 之前也说过, 这是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);
// 没有什么别的目的, 这时候Spring已经开始初始化所有Singleton Bean 了,
// 肯定不希望这时候还出现bean定义解析, 加载,注册
beanFactory.freezeConfiguration();
// 开始初始化
beanFactory.preInstantiateSingletons();
}
ConversionService
ConversionService 最有用的场景就是,它用来将前端传过来的参数和后端的 controller 方法上的参数进行绑定的时候用。
像前端传过来的字符串、整数要转换为后端的 String、Integer 很容易,但是如果 controller 方法需要的是一个枚举值,或者是 Date 这些非基础类型(含基础类型包装类)值的时候,我们就可以考虑采用 ConversionService 来进行转换。
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.javadoop.learning.utils.StringToEnumConverterFactory"/>
</list>
</property>
</bean>
ConversionService 接口很简单,所以要自定义一个 convert 的话也很简单。
下面再说一个实现这种转换很简单的方式,那就是实现 Converter 接口。
来看一个很简单的例子,这样比什么都管用。
public class StringToDateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
try {
return DateUtils.parseDate(source, "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "HH:mm:ss", "HH:mm");
} catch (ParseException e) {
return null;
}
}
}
只要注册这个 Bean 就可以了。这样,前端往后端传的时间描述字符串就很容易绑定成 Date 类型了,不需要其他任何操作。
从最后一行进入, 又到了 DefaultListableBeanFactory 类了, 这个类我们已经不陌生了
preInstantiateSingletons
// DefaultListableBeanFactory.java 728
@Override
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
// this.beanDefinitionNames 保留了所有的beanNames
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// 下面这个循环, 触发所有的非懒加载的singleton beans的初始化操作
for (String beanName : beanNames) {
// 合并父bean中的配置, 注意 <bean id="" class="" parent="" /> 中的parent, 用的不多
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 非抽象, 非懒加载的bean 如果配置了 abstract=true, 那就不需要初始化
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 处理FactoryBean
if (isFactoryBean(beanName)) {
// FactoryBean的话, 在beanName前面加上 '&' 符号, 再调用getBean()方法, getBean()方法先不急
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
// 判断当前FactoryBean是否是SmartFactoryBean的实现, 此处忽略
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
// 对于普通的bean, 只要调用getBean(beanName)这个方法就可以进行初始化了
getBean(beanName);
}
}
}
// 到这里, 所有的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(new PrivilegedAction<Object>() {
@Override
public Object run() {
smartSingleton.afterSingletonsInstantiated();
return null;
}
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
接下来我们就进入到了getBean(beanName)方法中了, 这个方法我们经常用来从beanFactory中获取一个bean, 而初始化的方法也在封装在了这个方法里.
getBean
在继续前进之前,先看看 FactoryBean 的预备知识
FactoryBean
FactoryBean 适用于 Bean 的创建过程比较复杂的场景,比如数据库连接池的创建。
public interface FactoryBean<T> {
T getObject() throws Exception;
Class<T> getObjectType();
boolean isSingleton();
}
public class Person {
private Car car ;
private void setCar(Car car){ this.car = car; }
}
我们假设现在需要创建一个 Person 的 Bean,首先我们需要一个 Car 的实例,我们这里假设 Car 的实例创建很麻烦,那么我们可以把创建 Car 的复杂过程包装起来:
public class MyCarFactoryBean implements FactoryBean<Car>{
private String make;
private int year ;
public void setMake(String m){ this.make =m ; }
public void setYear(int y){ this.year = y; }
public Car getObject(){
// 这里我们假设 Car 的实例化过程非常复杂,反正就不是几行代码可以写完的那种
CarBuilder cb = CarBuilder.car();
if(year!=0) cb.setYear(this.year);
if(StringUtils.hasText(this.make)) cb.setMake( this.make );
return cb.factory();
}
public Class<Car> getObjectType() { return Car.class ; }
public boolean isSingleton() { return false; }
}
我们看看装配的时候是怎么配置的:
<bean class = "com.javadoop.MyCarFactoryBean" id = "car">
<property name = "make" value ="Honda"/>
<property name = "year" value ="1984"/>
</bean>
<bean class = "com.javadoop.Person" id = "josh">
<property name = "car" ref = "car"/>
</bean>
看到不一样了吗?id 为 “car” 的 bean 其实指定的是一个 FactoryBean,不过配置的时候,我们直接让配置 Person 的 Bean 直接依赖于这个 FactoryBean 就可以了。中间的过程 Spring 已经封装好了。
说到这里,我们再来点干货。我们知道,现在还用 xml 配置 Bean 依赖的越来越少了,更多时候,我们可能会采用 java config 的方式来配置,这里有什么不一样呢?
@Configuration
public class CarConfiguration {
@Bean
public MyCarFactoryBean carFactoryBean(){
MyCarFactoryBean cfb = new MyCarFactoryBean();
cfb.setMake("Honda");
cfb.setYear(1984);
return cfb;
}
@Bean
public Person aPerson(){
Person person = new Person();
// 注意这里的不同
person.setCar(carFactoryBean().getObject());
return person;
}
}
这个时候,其实我们的思路也很简单,把 MyCarFactoryBean 看成是一个简单的 Bean 就可以了,不必理会什么 FactoryBean,它是不是 FactoryBean 和我们没关系。
// AbstractBeanFactory.java 195
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
// 我们剖析初始化bean的过程, 但是getBean方法我们经常是用来从容器中获取bean用的, 注意切换思路
// 已经初始化的bean就从容器中直接获取, 否则就先初始化再返回
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 获取一个"正统"的beanName, 处理两种情况:
// 一种是前面说的FactoryBean(名称前加 "&")
// 另一种就是别名, 因为这个方法是getBean, 获取bean用的, 传入一个别名也是可以的
final String beanName = transformedBeanName(name);
// 注意这个, 这是返回值
Object bean;
// 检查一下是不是已经创建过了
Object sharedInstance = getSingleton(beanName);
// 这里说下args, 虽然看上去不重要. 前面我们一路进来都是getBean(beanName),
// 所以这里args是null, 但是如果args不为null的时候, 说明想要调用方不是希望获取bean, 而是创建bean
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 + "'");
}
}
// 下面这个方法, 如果是普通Bean的话, 直接返回这个 sharedInstance
// 如果是FactoryBean, 返回他创建的那个实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果创建了此beanName的prototype类型的bean, 直接抛错
// 往往是因此陷入了循环引用
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 检查一下这个BeanDefinition是否存在容器中
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 如果当前容器中没有这个BeanDefinition, 看看父容器中有没有
String nameToLookup = originalBeanName(name);
if (args != null) {
// 返回父容器的查询结果
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
// typeCheckOnly为false, 将当前beanName放入一个alreadyCreated的Set集合中
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
// 到这里总结一下, 要准备创建bean了
// 对于Singleton的bean来说, 容器中还没有创建这个bean
// 对于prototype的bean来说, 本来就是要新创建一个bean
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 先初始化所有依赖的bean
// 注意, 这里依赖的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);
// 先初始化被依赖的bean
getBean(dep);
}
}
// 如果是Singleton scope , 创建Singleton实例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
// 执行创建bean, 详情后面说
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 如果是prototype scope的, 创建prototype实例
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);
}
// 如果不是Singleton或prototype的话, 需要委托给相应实现类进行处理
else {
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, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
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;
}
}
// 最后检查一下要返回的类型对不对, 不对的话抛异常, 对的话就返回了
if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
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;
}
接下来是分析 createBean 方法:
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
throws BeanCreationException;
第三个参数 args 代表的创建实例需要的参数, 就是给构造器的参数或者是给FactoryBean的参数. 不过在我们的初始化阶段, args为null
这会我们到了一个新的类了, AbstractAutowireCapableBeanFactory . 看类名, AutowireCapable, 类名是不是也说明了些问题? 自动装配的能力
主要是为了以下场景,采用 @Autowired 注解注入属性值:
public class MessageServiceImpl implements MessageService {
@Autowired
private UserService userService;
public String getMessage() {
return userService.getMessage();
}
}
<bean id="messageService" class="com.javadoop.example.MessageServiceImpl" />
以上这种属于混用了 xml 和 注解 两种方式的配置方式,Spring 会处理这种情况。
// AbstractAutowireCapableBeanFactory 447
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// 确保BeanDefinition中的class被加载
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// 准备方法覆写,这里又涉及到一个概念:MethodOverrides,它来自于 bean 定义中的 <lookup-method />
// 和 <replaced-method />,如果读者感兴趣,回到 bean 解析的地方看看对这两个标签的解析。
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 让 InstantiationAwareBeanPostProcessor 在这一步有机会返回代理
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);
}
// 重头戏 创建bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
创建 Bean
我们继续往里看 doCreateBean 这个方法:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 说明不是FactoryBean, 这里实例化bean, 非常关键. 细节之后再说
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 这里就是bean里面,我们定义的类的实例.
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
// 类型
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// 直接跳过 涉及接口 MergedBeanDefinitionPostProcessor
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");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 这一步也是非常关键的, 这一步负责属性装配, 因为前面只是实例化了, 并没有设值. 在这里设置属性值
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 还记得 init-method 吗?还有 InitializingBean 接口?还有 BeanPostProcessor 接口?
// 这里就是处理 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);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(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;
}
到这里,我们已经分析完了 doCreateBean()方法, 总的来说, 我们已经说完了整个初始化流程
接下来说说doCreateBean方法的三个细节.
一个是创建Bean的createBeanInstance方法, 一个是依赖注入的populateBean方法, 还有一个是回调initializeBean方法
创建bean实例
我们先看createBeanInstance方法, 挑重点的说,这个方法就是实例化我们指定的类.
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// 确保已经加载了此类
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());
}
if (mbd.getFactoryMethodName() != null) {
// 采用工厂方法实例化, 注意, 不是FactoryBean
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 如果不是第一次创建, 比如prototype创建第二次
// 这种情况下, 我们可以从第一次创建知道, 采用无参构造方法,还是构造函数依赖注入 来完成实例化
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);
}
挑个简单的无参构造函数构造实例来看看:
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<Object>() {
@Override
public Object run() {
return 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);
}
}
我们可以看到, 关键地方在于 :
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
这里会进行实际的实例化过程,我们进去看看:
// SimpleInstantiationStrategy 59
@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
// 如果不存在方法覆写, 就使用反射进行实例化. 否侧使用CGLIB
if (bd.getMethodOverrides().isEmpty()) {
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(new PrivilegedExceptionAction<Constructor<?>>() {
@Override
public Constructor<?> run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
// 利用构造方法进行实例化
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// 存在方法覆写, 利用CGLIB来完成实例化, 需要依赖CGLIB生成子类
// tips: 因为如果不使用 CGLIB 的话,存在 override 的情况 JDK 并没有提供相应的实例化支持
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
到这里,我们就算实例化完成了。我们开始说怎么进行属性注入。
bean属性注入
看完了 createBeanInstance(…) 方法,我们来看看 populateBean(…) 方法,该方法负责进行属性设值,处理依赖。
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
// bean实例的所有属性都在这里了
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
if (!pvs.isEmpty()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// 到这一步的时候, bean实例化完成 (通过工厂方法或构造函数) , 但是还没开始属性设值
// InstantiationAwareBeanPostProcessor 的实现类可以在这里对bean进行状态修改
// 我也没找到有实际的使用,所以我们暂且忽略这块吧
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;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 通过名字找到所有的属性值, 如果是bean依赖, 先初始化依赖的bean, 记录依赖关系
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 通过类型装配, 复杂一些
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
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;
// 这里有个非常有用的BeanPostProcessor进到这里 : AutowiredAnnotationBeanPostProcessor
// 对采用@Autowire, @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);
}
initializeBean
属性注入完成之后, 这一步其实就是处理回调了.这块代码比较简单
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
// 如果Bean实现了BeanNameAware, BeanClassLoaderAware, 或 BeanFactoryAware接口, 回调
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor的postProcessorBeforeInitialization回调
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的postProcessorAfterInitialization回调
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}