先来看一个简单使用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
<?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>
这是一个使用Spring的很简单的一个Demo,但是它包含从xml配置文件中读取bean信息注册到Spring容器中、解析xml中不同的标签、bean的加载、bean的获取等一系列Spring容器初始化到从Spring容器中获取bean操作
-
使用XmlBeanFactory初始化Spring IOC容器,XmlBeanFactory是一个很基础的Spring容器,虽然在Spring3.1开始已经不建议使用了
BeanFactory beanFactory=new XmlBeanFactory(new ClassPathResource("spring-context.xml"));
在上面一段代码中ClassPathResource
主要作用是加载指定的xml配置文件
/**
* 先是调用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(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初始化资源加载的真正实现
/**
* 先是调用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
// 作为成员变量定义在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进行了初始化
/**
* 先是调用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);
}
}