其實源碼是個好東西,好到讓你理解作者的初心和想法是如何一步步實現的,例如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加載機制單看一篇博文讀一篇文章就能掌握是不可能的,需要大家親自上手實踐,將大神的設計思想在讀源碼的過程中真正的掌握。