其实源码是个好东西,好到让你理解作者的初心和想法是如何一步步实现的,例如spring,我们更习惯于拿来当应用去使用,但适当的去研究下源码的实现就会掌握很多干货。
千万言不抵一书,梳理下spring的类加载机制,也是整理自己的思路,拿下边的一个demo作为入口 边撸代码边整理,开始:
public static void main(String[] args) {
@SuppressWarnings("resource")
ApplicationContext ac = new ClassPathXmlApplicationContext("servlet-context.xml");
Demo demo = (Demo) ac.getBean("demo");
System.out.println(demo.sayHelloWorld());
}
ApplicationContext ac = new ClassPathXmlApplicationContext("servlet-context.xml");
这一行代码就包含了spring容器如何创建bean的内容。对,短短一行。
来看下xml文件内容:
<beans:bean id="demo" class="com.github.bioinfo.webes.demo.Demo" scope="singleton" init-method="init">
<beans:property name="name" value=""></beans:property>
</beans:bean>
<beans:bean id="beanFactoryPostProcess" class="com.github.bioinfo.webes.demo.DemoBeanFactoryPostProcess"></beans:bean>
<beans:bean id="beanPostProcess" class="com.github.bioinfo.webes.demo.DemoBeanPostProcess"></beans:bean>
那spring容器是如何初始化配置文件中的bean的呢?这个是问题1,稍后解析,先分析下如上xml配置文件中beanFactoryPostProcess及beanPostProcess(问题2)。
为何要有这两个postprocess(后处理器)?以及他们的区别是什么?
BeanFactory:bean工厂,bean实例由此工厂获取,bean的初始化,主要包括了加载beanDefination,实例化两步。beanDefination类似于bean的特征的封装,包括了类全称,属性值,scope等bean的定义信息。那么在bean实例化前后是否能够添加一些自定义的动作来改变bean的属性或者直接改变原bean呢?可以的,提供这些可扩展动作的bean就叫做postProcess。
首先,beanFactoryPostProcess:该处理器是在bean的defination已加载完毕,但还未实例化前起作用的。回到配置文件中的<beans:bean id="beanFactoryPostProcess" class="com.github.bioinfo.webes.demo.DemoBeanFactoryPostProcess"></beans:bean>
看看该处理器的具体实现:
package com.github.bioinfo.webes.demo;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class DemoBeanFactoryPostProcess implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("beanFactoryPostProcess 执行了");
BeanDefinition definition = beanFactory.getBeanDefinition("demo");
MutablePropertyValues values = definition.getPropertyValues();
if(values.contains("name")) {
values.addPropertyValue("name", "beanFacotryPostProcess changed");
}
}
}
大体意思就是,实现该处理器接口的唯一方法postProcessBeanFactory
,该方法执行时beanDefination已经加载了,所以我们拿到beanid为demo的defination,然后循环其属性值,找到属性为name的property,将其值替换成beanFacotryPostProcess changed
。此时bean还未实例化。具体运行结果等剖析完beanPostProcess.
再看下beanPostProcess:该处理器接口有两个方法(如下已经实现):
package com.github.bioinfo.webes.demo;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class DemoBeanPostProcess implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("bean postprocess before inital at bean " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("bean postprocess after intial at bean " + beanName);
return bean;
}
}
这两个方法的执行一个是在bean已实例化,属性值已注入,但初始方法还未执行(postProcessBeforeInitialization);一个是在bean已实例化,属性值已注入,初始方法已执行后(postProcessAfterInitialization)。这里是否可以将AOP作为案例引入等我回头分析下。
ok,到这里我们已经分析了这两个主要的后处理器,并讲出了其差别,那么还剩它们作用的bean了,将该bean的实现贴出:
package com.github.bioinfo.webes.demo;
public class Demo {
public Demo() {
System.out.println("demo 构造函数被执行了");
}
public String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void init() {
System.out.println("Demo class init method");
}
public String sayHelloWorld() {
return "MyName is " + name;
}
}
注意,servlet-context.xml中的demo这个bean的定义有一个init-method=init的定义,此处是为了能够看出beanPostProcess的作用。
下面来看看main函数的执行结果:
2018-10-23 13:32:54 [INFO ](org.springframework.context.support.ClassPathXmlApplicationContext) (AbstractApplicationContext.java:582) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@52a86356: startup date [Tue Oct 23 13:32:54 CST 2018]; root of context hierarchy
2018-10-23 13:32:54 [INFO ](org.springframework.beans.factory.xml.XmlBeanDefinitionReader) (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [servlet-context.xml]
beanFactoryPostProcess 执行了
demo 构造函数被执行了
bean postprocess before inital at bean demo
Demo class init method
bean postprocess after intial at bean demo
MyName is beanFacotryPostProcess changed
顺序:
1、beanFacotryPostProcess在bean实例化前执行
2、bean构造成功(实例化)
3、beanPostProcess的beforeInital方法在demo实例的init方法前执行
4、demo实例的init方法执行(该方法在实例化和属性注入后会执行,在配置文件中init-method定义)
5、beanPostProcess的afterInitial方法在demo实例的init方法后执行
6、执行main函数中触发的sayHello方法
如上的后处理器在spring框架中有诸多实现,比如PropertyPlaceHolderConfigure就是BeanFacotryPostProcess的一种实现,其将bean中的属性占位符替换为property文件中的真实值,当然在bean实例化前。当然如上这些也是spring的bean加载过程的一部分。下面就来分析下问题1,整个bean的加载在spring framework中是如何进行的
研究spring的bean加载机制最好的办法就是网上找一篇前辈研究高质量文章先初步了解下加载机制,记住几个关键的处理步骤。然后自己再亲自debug。
仍然以上边的代码举例:
public static void main(String[] args) {
@SuppressWarnings("resource")
ApplicationContext ac = new ClassPathXmlApplicationContext("servlet-context.xml");
Demo demo = (Demo) ac.getBean("demo");
System.out.println(demo.sayHelloWorld());
}
进入ClassPathXmlApplicationContext
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
说明进入该类的另一个构造方法,进入得到:
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
1、先看继承的父类构造方法做的事情
在super(parent)
上打断点,一直进入直到底层的继承类AbstractApplicationContext
的构造方法:
public AbstractApplicationContext(ApplicationContext parent) {
this();
setParent(parent);
}
然后进入AbstractApplicationContext的this()
:
public AbstractApplicationContext() {
this.resourcePatternResolver = getResourcePatternResolver();
}
这里主要是获取了ResourceResolver并指给了resourcePatternResolver filed。
好奇心驱使看下getResourcePatternResolver()
:
/**
* Return the ResourcePatternResolver to use for resolving location patterns
* into Resource instances. Default is a
* {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver},
* supporting Ant-style location patterns.
* <p>Can be overridden in subclasses, for extended resolution strategies,
* for example in a web environment.
* <p><b>Do not call this when needing to resolve a location pattern.</b>
* Call the context's {@code getResources} method instead, which
* will delegate to the ResourcePatternResolver.
* @return the ResourcePatternResolver for this context
* @see #getResources
* @see org.springframework.core.io.support.PathMatchingResourcePatternResolver
*/
protected ResourcePatternResolver getResourcePatternResolver() {
return new PathMatchingResourcePatternResolver(this);
}
大致意思就是说获得了一个资源解析器,该解析器可以解析配置文件,配置文件servlet-context.xml也是一种资源嘛。
2、再看setConfigLocations(configLocations)
做了哪些事情
进去:
/**
* Set the config locations for this application context.
* <p>If not set, the implementation may use a default as appropriate.
*/
public void setConfigLocations(String... locations) {
if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
这里大体啥意思都看得懂,主要是this.configLocations[i] = resolvePath(locations[i]).trim();
这里的resolvePath()
,即将path中的占位符${…}解析成真实的环境属性值,并赋值给configLocations field。
注意,以上的赋值都是给到了ClassPathXmlApplicationContext
的不同级别的父类,因此这些field 都可以被低级别的子类看到。
3、重头戏:refresh()
这个方法是最重点的point,进入:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
这里参考前辈的文章,学习了几点精华之处:
1)synchronized (this.startupShutdownMonitor)
该锁锁住了startupShutdownMonitor
这个对象,因为在close()
方法中也同样锁住了该对象,所以在同一时间点不可能同时进行refresh和close动作。第二点优点在于相比锁住整个方法体,效率更高(具体可以自行研究哦)。
2)refresh()内用了模板模式,每一个方法的实现既可以由自身实现,也可以交给子类。层层递进,一目了然。
下面主要看一下如下这几个方法:
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
finishBeanFactoryInitialization(beanFactory);
这几个方法有的是由AbstractApplicationContext
本类实现,有的作为抽象方法,交由子类实现。
逐一剖析:
1)prepareRefresh()
protected void prepareRefresh() {
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
getEnvironment().validateRequiredProperties();
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
refresh前的准备工作:记录refresh时间,将active置为true,还做了一些其他工作(恕我没仔细看,感觉对理解bean的加载没有价值)。
2)obtainFreshBeanFactory()
得到一个beanFactory,并将BeanDefination注册到该bean中。进去看下:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
这里的refreshBeanFactory()
是重点,debug进入发现是AbstractRefreshableApplicationContext
子类实现了该方法:
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(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);
}
}
先判断是否有beanFactory,有则destroy然后close,接下来创建beanFactory:
DefaultListableBeanFactory beanFactory = createBeanFactory();
进入createBeanFactory()
如下:
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
返回了一个DefaultListableBeanFactory实例,该beanFacotry是AbstractBeanFactory
的一个子类,也是常用的beanFacotory。该bean工厂相当于一个容器,用来存放后续的beanDefination及bean实例等对象。
如下为DefaultListableBeanFactory
的部分field
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
/** Map of singleton and non-singleton bean names, keyed by dependency type */
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
/** List of bean definition names, in registration order */
private volatile List<String> beanDefinitionNames = new ArrayList<String>(256);
ok,出栈再回到refreshBeanFactory()
方法体:
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
没做详细研究,直接到重点loadBeanDefinitions(beanFactory)
:
该方法为AbstractRefreshableApplicationContext
的一个抽象方法,具体实现交由AbstractXmlApplicationContext
子类实现:
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);
}
大致意思就是new一个BeanDefinitionReader,对该reader设置了一下。然后重点在于loadBeanDefinitions(beanDefinitionReader)
:
这里比较繁琐,你debug一层层进去,发现做的事情就是ser读取vlet-context.xml中的bean,将bean的定义属性:class、scope init-method等属性信息写入BeanDefinition,存放在beanFactory中。
到此就新获得了一个beanFactory
。
接下来要将新获得的这个beanFactory作为入参传入后续的方法中。
Step1首先是prepareBeanFactory(beanFactory)
方法:
这里边包含了各种方法,但我觉得和探索加载机制关联性不大,略过,感兴趣的读者可以自行探索,有自己的心得可以不吝指教。
然后是postProcessBeanFactory(beanFactory)
,debug发现为空,这里作为抽象方法可以交由子类去定制化实现,比如最开始我自己实现的demoBeanFactoryPostProcess。
Step2再然后是invokeBeanFactoryPostProcessors(beanFactory)
,debug进去看下:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
这里重点是PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
,debug进去,代码有点多,先全部贴出来,然后着重点的讲:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<String>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
new LinkedList<BeanDefinitionRegistryPostProcessor>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryPostProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
registryPostProcessors.add(registryPostProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
registryPostProcessors.addAll(priorityOrderedPostProcessors);
invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(beanFactory, orderedPostProcessors);
registryPostProcessors.addAll(orderedPostProcessors);
invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);
registryPostProcessors.add(pp);
processedBeans.add(ppName);
pp.postProcessBeanDefinitionRegistry(registry);
reiterate = true;
}
}
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(beanFactory, orderedPostProcessors);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
前边依次判断beanFactoryPostProcessors是否为BeanDefinitionRegistryPostProcessor,由于beanFactoryPostProcessors作为第二个参数,debug为null。所以不走判断成功后的逻辑;从beanFactory中获取类型为BeanDefinitionRegistryPostProcessor
的beanName,debug为空,所以String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
postProcessNames为空,因此后边调用实现了PriorityOrdered、Ordered及other的BeanDefinitionRegistryPostProcessors,均为空,执行逻辑可忽略。直接到:
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
这里由于我们在配置文件里配置过beanid=beanFactoryPostProcess的beanfactorypostprocess,因此String[] postProcessorNames
为[beanFactoryPostProcess]
。一步步debug来到
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
由于beanFactory既不是PriorityOrdered也不是Ordered,所以加入nonOrderedPostProcessorNames,然后:
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
如上将DemoBeanFactoryPostProcess实例化放入nonOrderedPostProcessors。然后调用:
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
进去:
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
是不是很熟悉,调用DemoBeanFactoryPostProcess实例的postProcessBeanFactory方法,这个方法在第一部分已经详细介绍过。
Step3随后到了registerBeanPostProcessors(beanFactory)
,一直debug到关键代码段:
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(beanFactory, orderedPostProcessors);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(beanFactory, internalPostProcessors);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
逻辑和step2差不多,大体是获取beanFactory里的BeanPostProcess,判断其是否为PriorityOrdered、Ordered。发现均不是则放入nonOrderedPostProcessorNames。最后:
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
即将DemoPostProcess(结合咱们配置文件里的DemoPostProcess例子)注册(存放)到beanFactory中。
Step4到finishBeanFactoryInitialization(beanFactory)
,中间忽略了几个模板方法,因为觉得对理解bean加载没太大必要,这个方法中主要实现了bean的实例化。
再来回顾下前边已经实现的步骤:
1.1 obtainFreshBeanFactory()
得到一个beanFactory,并加载了所有beanDefinition。
1.2prepareBeanFactory(beanFactory)
对beanFactory做了些准备工作
1.3invokeBeanFactoryPostProcessors(beanFactory)
调用beanFactory后处理器,对bean进行未实例化前的处理
1.4registerBeanPostProcessors(beanFactory)
将BeanPostProcess注册(实例化并存放 )到BeanFactory
进入到finishBeanFactoryInitialization(beanFactory)
前边的代码可以带过,主要看beanFactory.preInstantiateSingletons()
,进入之(注:该方法是ConfigurableListableBeanFactory的一个抽象方法,debug可知由DefaultListableBeanFactory实现):
protected boolean isBeanEligibleForMetadataCaching(String beanName) {
return (this.configurationFrozen || super.isBeanEligibleForMetadataCaching(beanName));
}
@Override
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.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.
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
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 {
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
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();
}
}
}
}
先是获取已注册到beanFactory中的beanDefinitionNames:
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
依次是[demo, beanFactoryPostProcess, beanPostProcess]
接下来循环每个beanName,判断是否为BeanFactory,由于三个均不是,直接到getBean(beanName)
。进入:
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
debug进入:
检查是否已经实例化过
Object sharedInstance = getSingleton(beanName);
无则返回null,并进入Else,一路debug下来,来到实例化bean的核心代码段(由于例子中创建的bean均为默认的singleton):
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
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);
}
看下sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(){})
第二个参数是将一个匿名内部类传入,getSingleton()
方法最终调用了这个匿名内部类的getObject()
的createBean(beanName, mbd, args)
。debug进入:
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
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.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
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.
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);
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
直达核心部分:Object beanInstance = doCreateBean(beanName, mbdToUse, args);
这里入参 beanName=demo;
mdbToUse(beanDefinitiionToUse)=Root bean: class [com.github.bioinfo.webes.demo.Demo]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=init; destroyMethodName=null; defined in class path resource [servlet-context.xml];
args=null;
进入:
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) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
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");
}
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) {
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;
}
这里的核心是instanceWrapper = createBeanInstance(beanName, mbd, args);
进入分析下几个重点:
获取bean的class全称 beanClass=class com.github.bioinfo.webes.demo.Demo
Class<?> beanClass = resolveBeanClass(mbd, beanName);
return instantiateBean(beanName, mbd)
再进入:
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
debug进入:
SimpleInstantiationStrategy的instantiate()方法:
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
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 {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
划重点:
1.1 final Class<?> clazz = bd.getBeanClass();
得到clazz = class com.github.bioinfo.webes.demo.Demo
1.2 constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
得到Demo的构造器public com.github.bioinfo.webes.demo.Demo()
1.3BeanUtils.instantiateClass(constructorToUse)
具体实例化
这里利用了反射机制根据构造器将Demo类new一个instance出来。
好了,如上是层层debug得到的。
其实spring的初始化bean加载机制单看一篇博文读一篇文章就能掌握是不可能的,需要大家亲自上手实践,将大神的设计思想在读源码的过程中真正的掌握。