Spring 源碼分析(二)之 Spring IOC 容器源碼分析
在之前介紹了Spring IOC 容器在項(xiàng)目中的作用
- 將對(duì)象的構(gòu)建統(tǒng)一解決
- 并自動(dòng)維護(hù)對(duì)象的依賴關(guān)系磁椒,從而降低實(shí)現(xiàn)成本
- ...
源碼介紹之前,看幾個(gè)問(wèn)題:
- Bean的承載對(duì)象是什么本辐?
- Bean的定義如何存儲(chǔ)的医增?
- Bean工廠是如何生產(chǎn)bean的?
- Bean的依賴關(guān)系由誰(shuí)來(lái)解決茫多?
- Bean工廠和ApplicationContext的區(qū)別忽刽?
Bean的構(gòu)建過(guò)程
spring.xml文件中保存了我們對(duì)Bean的描述配置,BeanFactory會(huì)讀取這些配置然后生成對(duì)應(yīng)的Bean缔恳。
這些配置信息最后由BeanDefinition來(lái)承載。
BeanDefinition(Bean定義)
IOC實(shí)現(xiàn)中万细,我們?cè)趚ml中的描述的Bean信息最后都將保存至BeanDefinition對(duì)象中纸泄,其中xml bean與BeanDefinition是一對(duì)一的關(guān)系。
xml bean的屬性配置與BeanDefinition對(duì)應(yīng)關(guān)系
XML-Bean | BeanDefinition |
---|---|
class | beanClassName |
scope | SCOPE_SINGLETON雪营、SCOPE_PROTOTYPE |
lazy-init | AbstractBeanDefinition.lazyInit |
constructor-arg | AbstractBeanDefinition.ConstructorArgument |
property | AbstractBeanDefinition.propertyValues |
factory-method | AbstractBeanDefinition.factoryMethondName |
destroy-method | AbstractBeanDefinition.destroyMethodName |
init-method | AbstractBeanDefinition.initMethodName |
autowire | AbstractBeanDefinition.autowireMode |
id | |
name |
BeanDefinition.java
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String SCOPE_SINGLETON = "singleton";
String SCOPE_PROTOTYPE = "prototype";
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
...
}
AbstractBeanDefinition.java
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable {
public static final String SCOPE_DEFAULT = "";
public static final int AUTOWIRE_NO = 0;
public static final int AUTOWIRE_BY_NAME = 1;
public static final int AUTOWIRE_BY_TYPE = 2;
public static final int AUTOWIRE_CONSTRUCTOR = 3;
/** @deprecated */
@Deprecated
public static final int AUTOWIRE_AUTODETECT = 4;
public static final int DEPENDENCY_CHECK_NONE = 0;
public static final int DEPENDENCY_CHECK_OBJECTS = 1;
public static final int DEPENDENCY_CHECK_SIMPLE = 2;
public static final int DEPENDENCY_CHECK_ALL = 3;
public static final String INFER_METHOD = "(inferred)";
private volatile Object beanClass;
private String scope;
private boolean abstractFlag;
private boolean lazyInit;
private int autowireMode;
private int dependencyCheck;
private String[] dependsOn;
private boolean autowireCandidate;
private boolean primary;
private final Map<String, AutowireCandidateQualifier> qualifiers;
private boolean nonPublicAccessAllowed;
private boolean lenientConstructorResolution;
private String factoryBeanName;
private String factoryMethodName;
private ConstructorArgumentValues constructorArgumentValues;
private MutablePropertyValues propertyValues;
private MethodOverrides methodOverrides;
private String initMethodName;
private String destroyMethodName;
private boolean enforceInitMethod;
private boolean enforceDestroyMethod;
private boolean synthetic;
private int role;
private String description;
private Resource resource;
...
}
BeanDefinitionRegistry(Bean注冊(cè)器)
在上面沒(méi)有看到xml bean中的id献起、name屬性對(duì)應(yīng)在bean定義中,原因是id其作為當(dāng)前bean的存儲(chǔ)key注冊(cè)到BeanDefinitionRegistry注冊(cè)器中姻政。name作為別名key注冊(cè)到AliasRegistry注冊(cè)中心岂嗓。其最后都是指向?qū)ο蟮腂eanDefinition。
BeanDefinitionRegistry.java
public interface BeanDefinitionRegistry extends AliasRegistry {
void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;
void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
boolean containsBeanDefinition(String var1);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
boolean isBeanNameInUse(String var1);
}
AliasRegistry.java
public interface AliasRegistry {
void registerAlias(String var1, String var2);
void removeAlias(String var1);
boolean isAlias(String var1);
String[] getAliases(String var1);
}
BeanDefinitionReader(Bean定義讀取)
前面知道了BeanDefinition存儲(chǔ)了xml bean信息食绿,而BeanDefinitionRegistry基于id和name保存bean的定義公罕,下面是xml bean到BeanDefinition然后注冊(cè)到BeanDefinitionRegistry整個(gè)過(guò)程。
分為3步:
1熏兄、BeanDefinitionReader讀取spring.xml
2树姨、讀取后創(chuàng)建BeanDefinition
3、創(chuàng)建好后注冊(cè)到BeanDefinitionRegister
BeanDefinitionReader.java
public interface BeanDefinitionReader {
//獲取注冊(cè)器
BeanDefinitionRegistry getRegistry();
//獲取資源裝載器
ResourceLoader getResourceLoader();
//獲取bean類加載器
ClassLoader getBeanClassLoader();
BeanNameGenerator getBeanNameGenerator();
//基于資源裝載Bean定義并注冊(cè)到注冊(cè)器
int loadBeanDefinitions(Resource var1) throws BeanDefinitionStoreException;
int loadBeanDefinitions(Resource... var1) throws BeanDefinitionStoreException;
//基于資源路徑裝載Bean定義并注冊(cè)到注冊(cè)器
int loadBeanDefinitions(String var1) throws BeanDefinitionStoreException;
int loadBeanDefinitions(String... var1) throws BeanDefinitionStoreException;
}
裝載過(guò)程demo
package com.demo.spring;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import java.util.Arrays;
/**
* com.demo.spring
*
* @author Zyy
* @date 2019/2/13 11:34
*/
public class BeanDefinitionReaderTest {
public static void main(String[] args) {
//創(chuàng)建一個(gè)簡(jiǎn)單注冊(cè)器
BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
//創(chuàng)建bean定義讀取器
BeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
//創(chuàng)建資源讀取器
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
//獲取資源
Resource resource = resourceLoader.getResource("spring.xml");
//裝載類定義
reader.loadBeanDefinitions(resource);
//打印構(gòu)建bean名稱
System.out.println(Arrays.toString(registry.getBeanDefinitionNames()));
}
}
運(yùn)行結(jié)果
[di, driver, com.demo.spring.HelloSpring#0, com.demo.spring.LookUpTest#0, helloSpring, com.demo.spring.DI#1, com.demo.spring.DI#0, helloByName]
如果未給bean設(shè)置id則:class+#+索引,來(lái)標(biāo)識(shí)id
com.demo.spring.HelloSpring#0
打印一下bean定義信息
spring.xml
<bean id="di" name="di2" lazy-init="false" class="com.demo.spring.DI" scope="singleton" init-method="init" destroy-method="destroy"/>
打印語(yǔ)句:
System.out.println(registry.getBeanDefinition("di"));
System.out.println(registry.getAliases("di2"));
結(jié)果信息:
Generic bean: class [com.demo.spring.DI]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=init; destroyMethodName=destroy; defined in class path resource [spring.xml]
[Ljava.lang.String;@73a28541
BeanFactory(bean工廠)
有了Bean的定義转晰,則下面可以用BeanFactory來(lái)進(jìn)行構(gòu)建bean。
BeanFactory.java
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
//基于id或name獲取一個(gè)bean
Object getBean(String name) throws BeansException;
//基于bean的類別獲取bean(如果出現(xiàn)多個(gè)該類的實(shí)例蔗崎,則會(huì)報(bào)錯(cuò))但是可以指定primary="true"調(diào)整優(yōu)先級(jí)來(lái)解決該報(bào)錯(cuò)
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
//基于名詞獲取一個(gè)bean扰藕,并覆蓋默認(rèn)的構(gòu)造參數(shù)
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
//指定bean與指定class是否匹配
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}
測(cè)試demo如下:
package com.demo.spring;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.DefaultResourceLoader;
/**
* com.demo.spring
*
* @author Zyy
* @date 2019/2/13 12:19
*/
public class BeanFactoryTest {
public static void main(String[] args) {
//注冊(cè)中心
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//讀取器
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
//設(shè)置資源加載器
reader.setResourceLoader(new DefaultResourceLoader());
//裝載構(gòu)建bean的定義
reader.loadBeanDefinitions("spring.xml");
//打印
System.out.println(beanFactory.getBean("di"));
System.out.println(beanFactory.getBean("di2"));
}
}
當(dāng)getBean時(shí)邓深,看下堆棧信息,如下
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:142)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1147)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1099)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
- locked <0x593> (a java.util.concurrent.ConcurrentHashMap)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at com.demo.spring.BeanFactoryTest.main(BeanFactoryTest.java:25)
看具體調(diào)用方法
instantiateClass:142, BeanUtils (org.springframework.beans)
instantiate:89, SimpleInstantiationStrategy (org.springframework.beans.factory.support)
instantiateBean:1147, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBeanInstance:1099, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:513, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:483, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
getObject:306, AbstractBeanFactory$1 (org.springframework.beans.factory.support)
getSingleton:230, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:302, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:197, AbstractBeanFactory (org.springframework.beans.factory.support)
main:25, BeanFactoryTest (com.demo.spring)
逐個(gè)點(diǎn)進(jìn)去查看
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
AbstractBeanFactory#getBean中繼續(xù)調(diào)用doGetBean冬耿,查看doGetBean亦镶,由于其中代碼太多日月,刪除檢查判斷山孔,只保留核心代碼
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//從單例緩存中獲取
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// Check if bean definition exists in this factory.
//從父類工廠中獲取
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// Create bean instance.
//mbd -> RootBeanDefinition
//判斷是否單例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
...
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
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 {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
...
}
}
}
catch (BeansException ex) {
...
}
}
return (T) bean;
}
其中
Object sharedInstance = getSingleton(beanName);
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
//如果取到的為null且判斷是正在創(chuàng)建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//則鎖住map
synchronized (this.singletonObjects) {
//從正在創(chuàng)建的earlySingletonObjects這個(gè)map中去取
singletonObject = this.earlySingletonObjects.get(beanName);
//如果還是取不到
if (singletonObject == null && allowEarlyReference) {
//從工廠獲取
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
//如果獲取到
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
//獲取到則放到緩存中
this.earlySingletonObjects.put(beanName, singletonObject);
//從工廠中移除
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
其中singletonObjects、earlySingletonObjects勒庄、singletonFactories均是一個(gè)map
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
對(duì)于其中的
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
其中如果是FactoryBean,則調(diào)用getObject()來(lái)獲取我們自定義的bean荡碾,例如
<!-- FactoryBean創(chuàng)建 自定義創(chuàng)建bean-->
<bean id="driver" class="com.demo.spring.DriverFactoryBean" >
<property name="jdbcUrl" value="jdbc:mysql://192.168.5.104:3306"></property>
</bean>
其中返回的不是DriverFactoryBean局装,而是返回Driver
public Class<?> getObjectType() {
return Driver.class;
}
總結(jié):
1、調(diào)用BeanFactory.getBean()會(huì)觸發(fā)Bean的實(shí)例化铐尚。
2、DefaultSingletonBeanRegistry中緩存了單例Bean玫膀。
3、Bean的創(chuàng)建于初始化是由AbstractAutowireCapableBeanFactory完成的帖旨。
另外:
IOC容器只存放單例Bean灵妨,IOC容器在初始化的時(shí)候,會(huì)將所以Bean初始化在singletonObjects這個(gè)ConcurrentHashMap中泌霍。
在獲取bean的時(shí)候,首先會(huì)去singletonObjects中去取碉熄,如果scope是單例則可以獲取bean,如果是多例锈津,則取不到bean,需要從mergedBeanDefinitions這個(gè)ConcurrentHashMap中獲取RootBeanDefinition琼梆,這個(gè)里面包含bean的基礎(chǔ)信息,然后判斷scope是prototype(多例)茎杂,則每次都會(huì)創(chuàng)建一個(gè)新的實(shí)例。
對(duì)于@Autowire煌往、@Resource等注解,在啟動(dòng)SpringIOC容器時(shí)羞海,容器會(huì)裝載一個(gè)AutowiredAnnotationBeanPostProcessor 后置處理器,當(dāng)容易掃描到@Autowire却邓、@Resource等注解時(shí)院水,就會(huì)在IOC容器中自動(dòng)查找需要的Bean,并裝配給該對(duì)象的屬性檬某,在使用@Autowire時(shí),首先在容器中查詢對(duì)應(yīng)類型的bean橙喘,如果查詢不止一個(gè),則根據(jù)名稱來(lái)查,如果名稱沒(méi)有則拋異常初坠,可以將required=false來(lái)解決,如果正好查詢到一個(gè)碟刺,則就將該bean裝配給@Autowire指定的變量。
對(duì)于bean之間相互引用的情況半沽,比如A依賴B,B依賴A者填,這種情況時(shí),先去實(shí)例化A心墅,然后發(fā)現(xiàn)依賴B酿矢,接著去實(shí)例化B瘫筐,如果此時(shí)發(fā)現(xiàn)B依賴A,容器會(huì)獲取A的一個(gè)早期引用(early reference)策肝,將這個(gè)早期引用的A注入給B隐绵,然后B實(shí)例化完了,則實(shí)例化A也就完成了氢橙。當(dāng)然對(duì)于這種循環(huán)引用的代碼應(yīng)該規(guī)避,這種不是正常的場(chǎng)景帘睦。
涉及的類:
BeanDefinition
DefaultResourceLoader
XmlBeanDefinitionReader
BeanDefinitionRegistry
BeanFactory
DefaultListableBeanFactory
AutowireCapableBeanFactory
AbstractAutowireCapableBeanFactory
SingletonBeanRegistry
DefaultSingletonBeanRegistry
整個(gè)流程:
run->getBean->BeanFactory->doGetBean->AbstructBeanFactory
->getSingleton(從緩存中獲取坦康,如果是單例,為空則創(chuàng)建并緩存滞欠,如果是多例則直接創(chuàng)建)
->DefaultSingleonBeanRegistry->createBean->AbstractAutowireCapableBeanFactory
->createBeanInstance->newInstance->Constructor->反射實(shí)例化Bean
BeanFactory 與 ApplicationContext區(qū)別
看下結(jié)構(gòu)圖
ApplicationContext.java
從圖中可以看到ApplicationContext是由BeanFactory接口派生出來(lái)的,具有BeanFactory所以功能逸绎。除此之外夭谤,還具有以下功能:
1、MessageSource朗儒,提供國(guó)際化的消息訪問(wèn)
2、資源訪問(wèn)醉锄,入url和文件
3、事件傳播恳不,實(shí)現(xiàn)了ApplicationListener接口的bean
4、載入多個(gè)上下文(有繼承關(guān)系)识啦,使每個(gè)上下文都專注于一個(gè)特定的層次负蚊,比如應(yīng)用web層
類似的
DefaultListableBeanFactory.java
github地址 : https://github.com/zhaoyybalabala/spring-test
如有問(wèn)題家妆,歡迎提問(wèn):)