å æ¥çä¸ä¸ªç®å使ç¨SpringçDemo
- BuildTest
public class BuildTest { @Test public void testBean(){ BeanFactory beanFactory=new XmlBeanFactory(new ClassPathResource("spring-context.xml")); TestBean testBean=(TestBean) beanFactory.getBean("testBean"); System.out.println(testBean.getStr()); } }
- TestBean
public class TestBean { private String str = "Hello Spring"; public String getStr() { return str; } public void setStr(String str) { this.str = str;} }
- spring-context.xml
è¿æ¯ä¸ä¸ªä½¿ç¨Springçå¾ç®åçä¸ä¸ªDemoï¼ä½æ¯å®å å«ä»xmlé ç½®æ件ä¸è¯»åbeanä¿¡æ¯æ³¨åå°Spring容å¨ä¸ã解æxmlä¸ä¸åçæ ç¾ãbeançå è½½ãbeançè·åçä¸ç³»åSpring容å¨åå§åå°ä»Spring容å¨ä¸è·åbeanæä½<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="testBean" class="com.wyj.learning.build.bean.TestBean"/> </beans>
- 使ç¨XmlBeanFactoryåå§åSpring IOC容å¨ï¼XmlBeanFactoryæ¯ä¸ä¸ªå¾åºç¡çSpring容å¨ï¼è½ç¶å¨Spring3.1å¼å§å·²ç»ä¸å»ºè®®ä½¿ç¨äº
å¨ä¸é¢ä¸æ®µä»£ç ä¸
ClassPathResource
主è¦ä½ç¨æ¯å è½½æå®çxmlé ç½®æ件
-
å æ¥çä¸ä¸
åå§åçæºç ClassPathResource
/**
* å
æ¯è°ç¨ClassPathResource(String path)带åæé æ¹æ³
*/
public ClassPathResource(String path) {
this(path, (ClassLoader) null);
}
/**
* è°ç¨ClassPathResource(String path, @Nullable ClassLoader classLoader)带åæé æ¹æ³
*/
public ClassPathResource(String path, @Nullable ClassLoader classLoader) {
Assert.notNull(path, "Path must not be null"); // 对xmlçè·¯å¾è¿è¡å¤ææ¯å¦ä¸ºnull
String pathToUse = StringUtils.cleanPath(path); // ç¨æ¥å¤çè·¯å¾ä¸ç'\'ï¼'/'
if (pathToUse.startsWith("/")) {
pathToUse = pathToUse.substring(1);
}
this.path = pathToUse; // path为xmlé
ç½®æ件çè·¯å¾
this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader()); // åå§åclassLoader
}
çå®æºç åç°åå§å
ClassPathResource
å°±åäºä¸¤ä»¶äºï¼è·åxmlé ç½®æ件çè·¯å¾ååå§åclassLoader
-
åæ¥ç
åå§åçæºç XmlBeanFactory
/**
* å
æ¯è°ç¨XmlBeanFactory(Resource resource)带åæé æ¹æ³ï¼åæ°ä¸ºResourceåå§åè¿åç对象
*/
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
/**
* è°ç¨XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory)带åæé æ¹æ³
*/
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory); // è°ç¨ç¶ç±»DefaultListableBeanFactoryæé æ¹æ³åå§å
this.reader.loadBeanDefinitions(resource); // springåå§åèµæºå è½½ççæ£å®ç°
}
æ¤æ¶å¨
XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory)
æé æ¹æ³ä¸æ两è¡ä»£ç ï¼
super(parentBeanFactory)
ï¼ç¨æ¥åå§åç¶ç±»
this.reader.loadBeanDefinitions(resource)
ï¼springåå§åèµæºå è½½ççæ£å®ç°
-
çç
çæºç super(parentBeanFactory)
/**
* å
æ¯è°ç¨DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory)带åæé æ¹æ³
*/
public DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
super(parentBeanFactory);
}
/**
* è°ç¨ç¶ç±»AbstractAutowireCapableBeanFactoryä¸AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory)带åæé æ¹æ³
*/
public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
this(); // è°ç¨æ¬ç±»æ åæé æ¹æ³åå§å
setParentBeanFactory(parentBeanFactory);
}
/**
* è°ç¨AbstractAutowireCapableBeanFactory()æ åæé æ¹æ³
*/
public AbstractAutowireCapableBeanFactory() {
super(); // è°ç¨ç¶ç±»æ½è±¡ç±»AbstractBeanFactoryçæ åæé æ¹æ³ï¼éé¢æ¯ç©ºå®ç°
ignoreDependencyInterface(BeanNameAware.class);
ignoreDependencyInterface(BeanFactoryAware.class);
ignoreDependencyInterface(BeanClassLoaderAware.class);
}
/**
* è¿éè°ç¨äºä¸æ¬¡è¯¥æ¹æ³ï¼è¯¥æ¹æ³ä¸»è¦åè½æ¯æ·»å éè¦å¿½ç¥æå®æ¥å£å®ç°ç±»çèªå¨è£
é
*/
public void ignoreDependencyInterface(Class<?> ifc) {
this.ignoredDependencyInterfaces.add(ifc);
}
/**
* è¿æ¯parentBeanFactoryï¼å¨åå§åXmlBeanFactory容å¨çæ¶åparentBeanFactory为nullï¼ï¼æ以æåparentBeanFactory为null
*/
@Override
public void setParentBeanFactory(@Nullable BeanFactory parentBeanFactory) {
if (this.parentBeanFactory != null && this.parentBeanFactory != parentBeanFactory) {
throw new IllegalStateException("Already associated with parent BeanFactory: " + this.parentBeanFactory);
}
this.parentBeanFactory = parentBeanFactory;
}
çå®
super(parentBeanFactory)
çæºç åç°å°±åäºä¸¤ä»¶äºï¼è·åæ·»å éè¦å¿½ç¥æå®æ¥å£å®ç°ç±»çèªå¨è£ é ååå§åparentBeanFactoryï¼ä½æ¯å¨XmlBeanFactory容å¨åå§åçæ¶åparentBeanFactory为null
-
å¨ç
çæºç ä¹åå æ¥çä¸ä¸readerçåå§åthis.reader.loadBeanDefinitions(resource)
// ä½ä¸ºæååéå®ä¹å¨XmlBeanFactoryä¸ï¼this代表å½åXmlBeanFactory对象
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
/**
* å
æ¯è°ç¨XmlBeanDefinitionReader(BeanDefinitionRegistry registry)带åæé æ¹æ³
*/
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
super(registry);
}
/**
* è°ç¨ç¶ç±»AbstractBeanDefinitionReaderä¸AbstractBeanDefinitionReader(BeanDefinitionRegistry registry)带åæé æ¹æ³
*/
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
// ç¡®å®è¦ä½¿ç¨çregistryæ¯å¦æ¯ResourceLoaderçå®ç°ç±»æ¥åå§åresourceLoader
if (this.registry instanceof ResourceLoader) {
this.resourceLoader = (ResourceLoader) this.registry;
}
else {
this.resourceLoader = new PathMatchingResourcePatternResolver();
}
// åå§å
if (this.regenvironmentistry instanceof EnvironmentCapable) {
this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
}
else {
this.environment = new StandardEnvironment();
}
}
çå®
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this)
çæºç ï¼éé¢ä» ä» åªæ¯å¯¹resourceLoaderåenvironmentè¿è¡äºåå§å
-
åæ¥ç
çæºç this.reader.loadBeanDefinitions(resource)
/**
* å
æ¯è°ç¨DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory)带åæé æ¹æ³
*/
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
/**
* è°ç¨EncodedResourceä¸EncodedResource(Resource resource)æé æ¹æ³åå§åEncodedResource对象
*/
public EncodedResource(Resource resource) {
this(resource, null, null);
}
/**
* è°ç¨EncodedResource(Resource resource, @Nullable String encoding, @Nullable Charset charset)æ¥åå§åresourceãencodingåcharset
*/
private EncodedResource(Resource resource, @Nullable String encoding, @Nullable Charset charset) {
super(); // 空å®ç°
Assert.notNull(resource, "Resource must not be null");
this.resource = resource;
this.encoding = encoding;
this.charset = charset;
}
/**
* ä»xmlé
ç½®æ件ä¸å è½½beanï¼ä¸»è¦æ¯è°ç¨doLoadBeanDefinitions(inputSource, encodedResource.getResource())æ¹æ³æ¥å®ç°ç
*/
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);
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); // çæ£å®ç°ä»xmlé
ç½®æ件å è½½bean
}
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();
}
}
}
/**
* çæ£å®ç°ä»xmlé
ç½®æ件å è½½bean
*/
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
Document doc = doLoadDocument(inputSource, resource); // è¿éæ¯ä»xmlé
ç½®æ件ä¸è·åDocument
return registerBeanDefinitions(doc, resource); // 解æ并注åbean
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
}
catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
}
catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}
/**
* æ ¹æ®ä»xmlé
ç½®æ件ä¸è§£æåºæ¥çDocument对象æ¥è§£æ并注åbean
*/
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 使ç¨DefaultBeanDeFinitionDocumentReaderå®ä¾åBeanDefinitionDocumentReader
// å¨å®ä¾åBeanDefinitionReaderæ¶åä¼å°BeanDefinitionRegisterä¼ å
¥ï¼é»è®¤ä½¿ç¨ç»§æ¿èªDefaultListableBeanFactoryçåç±»
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// è®°å½ç»è®¡åBeanDefinitionçå 载个æ°
int countBefore = getRegistry().getBeanDefinitionCount();
// å è½½å注åbean
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
// è®°å½æ¬æ¬¡å è½½çBeanDefinition个æ°
return getRegistry().getBeanDefinitionCount() - countBefore;
}
/**
* è·åxmlé
ç½®æ件ä¸çroot
*/
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement(); // è·årootï¼ä»¥ä¾¿å次å°rootä½ä¸ºåæ°ç»§ç»BeanDefinitionç注å
doRegisterBeanDefinitions(root); // 继ç»è§£æroot
}
/**
* æ ¹æ®xmlé
ç½®æ件ä¸ç<beans/>å®ä¹æ¥è§£ææ¯ä¸ä¸ªbean
*/
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); // 对profileç¯å¢è¿è¡å¤ç
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray( // è·åprofileå符串æ°ç»
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
preProcessXml(root); // 解æåå¤çï¼çç»åç±»å®ç°ï¼è¿ä¸¤ä¸ªæ¹æ³æ¯ç»åç±»è设计çï¼è¿æ¯æ¨¡æ¿è®¾è®¡æ¨¡å¼
parseBeanDefinitions(root, this.delegate); // 对xmlé
ç½®æ件ç读å
postProcessXml(root); // 解æåå¤çï¼çç»åç±»å®ç°
this.delegate = parent;
}
/**
* 对xmlé
ç½®æ件ç读åï¼è§£æææ¡£ä¸æ ¹çº§å«çå
ç´ importãaliasãbean
*/
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
// 对beansçå¤ç
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)) {
parseDefaultElement(ele, delegate); // 对beanãbeansãaliasãimportå
ç´ æ ç¾çå¤ç
}
else {
// 对beançå¤ç
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
/**
* 对beanãbeansãaliasãimportå
ç´ æ ç¾çå¤ç
*/
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// public static final String IMPORT_ELEMENT = "import";
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { // å½èç¹ä¸ºimportæ¶
importBeanDefinitionResource(ele);
}
// public static final String ALIAS_ELEMENT = "alias";
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { // å½èç¹ä¸ºaliasæ¶
processAliasRegistration(ele);
}
// public static final String BEAN_ELEMENT = "bean"
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { // å½èç¹ä¸ºbeanæ¶
processBeanDefinition(ele, delegate);
}
// public static final String NESTED_BEANS_ELEMENT = "beans";
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // å½èç¹ä¸ºbeansæ¶
// recurse
doRegisterBeanDefinitions(ele);
}
}