一丁稀、前言
學(xué)習(xí)Spring已經(jīng)有一段時間了辆脸,一直對spring的源碼比較好奇,因此開始準(zhǔn)備對Spring的源碼進行學(xué)習(xí)蕾管。這篇就從最簡單的HelloWord開始
二阔馋、分析
Java代碼
public class Person {
public Person() {
System.out.println("Person execute");
}
private String name ;
private Integer id ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
applicationContext.xml
<bean name="personName1" class="com.lw.spring.bean.Person" id="person1"></bean>
測試
public class Test {
@SuppressWarnings("deprecation")
public static void main(String[] args) {
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
Person p = (Person) bf.getBean("person1");
System.out.println(p);
}
}
我們平常使用更多的應(yīng)該是如下的加載方式
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
其實BeanFactory才是整個IOC容器的祖宗。其它的不過是對其補充娇掏。
- XmlBeanFactory:自定義XML讀取器,下面會介紹到.
- ApplicationContext:這其實又是一個體系的IOC容器了呕寝,只不過比較高級,后面會寫文章介紹到.
源碼分析
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
// 這個reader就是XMLBeanFactory對其父類DefaultListableBeanFactory的補充
this.reader.loadBeanDefinitions(resource);
}
我們可以看看整個XMLBeanFactory的整個代碼,可以發(fā)現(xiàn)整個XMLBeanFactory除了添加了個XmlBeanDefinitionReader 之外婴梧,并沒有添加其它什么東西.
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
}
下面進入到讀取器XmlBeanDefinitionReader 的代碼
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded =
new NamedThreadLocal<Set<EncodedResource>>("XML bean definition resources currently being loaded");
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
// 通過本地線程獲取一個封裝EncodedResource的Set集合
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
// 如果為null,則創(chuàng)建并且綁定當(dāng)前線程
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
// 將applicationContext.xml添加到集合當(dāng)中
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 加載BeanDefinition
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
比較重要的地方做了注釋.其中BeanDefinition其實就是<bean/>標(biāo)簽在Spring內(nèi)部的表現(xiàn)形式.
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 加載Document文檔
Document doc = doLoadDocument(inputSource, resource);
// 注冊BeanDefinition
return registerBeanDefinitions(doc, resource);
}
catch (Exception ex) {
// some exception
}
}
上面第一步加載Document使用的sax解析下梢,就不詳細(xì)看,主要來看注冊BeanDefinition.
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
繼續(xù)
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
return;
}
}
}
// 解析BeanDefinition之前應(yīng)該做的操作,空方法
preProcessXml(root);
// 解析BeanDefinition
parseBeanDefinitions(root, this.delegate);
// 解析BeanDefinition之后應(yīng)該做的操作,空方法
postProcessXml(root);
this.delegate = parent;
}
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
// 解析默認(rèn)標(biāo)簽
parseDefaultElement(ele, delegate);
}
else {
// 解析用戶自定義標(biāo)簽
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
上面解析默認(rèn)標(biāo)簽其實就是bean塞蹭、import之類的了孽江。解析標(biāo)簽時候同時也會解析其屬性,由于太過復(fù)雜番电,就沒有深入下去了岗屏。
BeanDefinition
上面提到過<bean/>標(biāo)簽在Spring內(nèi)部的表現(xiàn)形式其實就是BeanDefinition,而BeanDefinition只是一個接口漱办,它有哪些實現(xiàn)類呢这刷?
- ChildBeanDefinition
- GenericBeanDefinition
- RootBeanDefinition
其中RootBeanDefinition就是我們通常的bean了。
OK娩井、這篇就簡單到這里了暇屋。其實這里只是簡單的分析一行代碼,下一篇將會分析Bean是如何獲取的洞辣。