最近在看<spring源码深度解析>这本书,自己在GitHub上也下载了源码,DEBUG配合着看,做点笔记,加深下印象!巩固下知识.顺道给大伙分享下,有问题多多指教。一起进步哈。
版本:spring5.1.x
@Test
public void testSimpleLoad(){
//xmlBeanFactory 方式
//整个xml的解析都是在这步完成的
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFactoryTest.xml"));
//创建获取bean的过程
MyTestBean bean = (MyTestBean) bf.getBean("myTestBean");
Assert.notNull(bean,"Bean must be not null !");
}
XmlBeanFactory这种获取bean的方式已经被废弃了,不推荐使用,但无所谓,主要目的是看他的bean的获取的整个流程。
BeanFactory bf = new XmlBeanFactory(new ClassPathResource(“beanFactoryTest.xml”));
时序图:
测试代码很清晰,通过XmlBeanFactory()构造方法执行xml文件的读取,解析等操作,我们先看下XmlBeanFactory这类的UML图,关联确实有点复杂
再看下XmlBeanFactory这类的代码
@Deprecated
@SuppressWarnings({"serial", "all"})
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
/**
* Create a new XmlBeanFactory with the given resource,
* which must be parsable using DOM.
* @param resource the XML resource to load bean definitions from
* @throws BeansException in case of loading or parsing errors
*/
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
/**
* Create a new XmlBeanFactory with the given input stream,
* which must be parsable using DOM.
* @param resource the XML resource to load bean definitions from
* @param parentBeanFactory parent bean factory
* @throws BeansException in case of loading or parsing errors
*/
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
}
这类很简单,通过XmlBeanDefinitionReader这类来解析xml文件,整个解析流程都是在 **this.reader.loadBeanDefinitions(resource)**这步完成的,其实spring框架的风格也是如此,方法很有层次的套着,这样整个代码看起来也比较清爽
看下super(parentBeanFactory) 这步最终的执行方法:
/**
* Create a new AbstractAutowireCapableBeanFactory.
*/
public AbstractAutowireCapableBeanFactory() {
super();
ignoreDependencyInterface(BeanNameAware.class);
ignoreDependencyInterface(BeanFactoryAware.class);
ignoreDependencyInterface(BeanClassLoaderAware.class);
}
这个ignoreDependencyInterface()的作用是实例化一个bean A 时,如果他自动装配了属性B
该属性B实现了BeanNameAware,或者BeanFactoryAware ,或者BeanClassLoaderAware接口,那么
会调用过滤接口不会实例化,就是这作用,书上的原话是:
举例来说当A中有属性B,那么当Spring在获取A的Bean的时候如果其属性B还没有初始化,那么Spring会自动初始化B,这也是Spring中提供的一个重要特性,但是某些情况下B不会被初始化,其中的一种情况就是B实现了BeanNameAware接口。Spring中是这样介绍的:自动装配时忽略给定的依赖接口,典型应用是通过其他方式解析Application上下文注册依赖,类似于BeanFactory通过BeanFactoryAware进行注入或者ApplicationContext通过ApplicationContextAware进行注入
/**
* Load bean definitions from the specified XML file.
* @param resource the resource descriptor for the XML file
* @return the number of bean definitions found
* @throws BeanDefinitionStoreException in case of loading or parsing errors
*/
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
继续走下去,看下这个EncodedResource的构造方法
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;
}
就是个编码属性的处理,继续,看下loadBeanDefinitions()方法
/**
* Load bean definitions from the specified XML file.
* @param encodedResource the resource descriptor for the XML file,
* allowing to specify an encoding to use for parsing the file
* @return the number of bean definitions found
* @throws BeanDefinitionStoreException in case of loading or parsing errors
*/
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isTraceEnabled()) {
logger.trace("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());
}
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的解析都是从这边开始处理的,里面嵌套着好几个方法
看下时序图:
这BeanFactory的实例创建大概就这个流程,具体的里面流程后面再更新。。。。