首先先看一下Spring是如何创建对象的
Spring创建对象
public interface IService {
public String hello();
}
public class ServiceImpl implements IService {
private String name;
@Override
public String hello() {
return "hello";
}
}
引入最小依赖POM&bean配置
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean id="service" class="com.wyh.spring.core.ServiceImpl"
init-method="hello">
</bean>
</beans>
使用XmlBeanFactory创建对象
public class BeanFactoryDemo {
public static void main(String[] args) {
XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
IService service = (IService) xmlBeanFactory.getBean("service");
String hello = service.hello();
System.out.println(hello);
}
}
Bean解析及注册
首先看下new XmlBeanFactory(new ClassPathResource("beans.xml"))
这行代码
1、构造ClassPathResource
获取到了Resource对象也就等于获取到了该资源文件,后面可以根据方法的定义对文件进行相关操作
public ClassPathResource(String path) {
this(path, (ClassLoader)null);
}
public ClassPathResource(String path, @Nullable ClassLoader classLoader) {
Assert.notNull(path, "Path must not be null");
String pathToUse = StringUtils.cleanPath(path);
if (pathToUse.startsWith("/")) {
pathToUse = pathToUse.substring(1);
}
this.path = pathToUse;
this.classLoader = classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader();
}
ClassPathResource.png
2、初始化XmlBeanFactory
先放一张UML类图,对整体结构有个了解
XmlBeanFactory
构造方法
/**
* 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);
}
super(parentBeanFactory);跟踪到父类AbstractAutowireCapableBeanFactory
/**
* Create a new AbstractAutowireCapableBeanFactory.
*/
public AbstractAutowireCapableBeanFactory() {
super();
ignoreDependencyInterface(BeanNameAware.class);
ignoreDependencyInterface(BeanFactoryAware.class);
ignoreDependencyInterface(BeanClassLoaderAware.class);
}
ignoreDependencyInterface方法主要功能是忽略给定接口的自动装配功能。
例如:A有属性B,当Spring获取A对象时,B没有初始化,先初始化B。
下面重要的关键是loadBeanDefinitions方法,借了张时序图
image.png
- 封装资源文件
- 获取输入流
- 通过构造InputSource和Resource继续执行doLoadBeanDefinitions()
doLoadBeanDefinitions函数里主要做了三件事:
- 获取对XML文件的验证模式
- 加载XML文件,获取相应的Document
- 根据返回Document注册Bean信息
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
Document doc = doLoadDocument(inputSource, resource);
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
......
}
流程图:
image.png
网友评论