您的位置:首页 > 编程语言 > Java开发

Spring源码分析(1)-IoC容器的实现

2018-11-29 12:02 696 查看

最近在看《Spring技术内幕》这本书学习Spring的技术源码,写博客来记录自己的学习过程。

第一章

这一章主要介绍了Spring的子项目和核心实现、Spring出现的目标。

第二章-IoC容器的实现

控制反转

主动获取依赖的过程:Test对象需要用到Hello属性对象的时候,自己创建一个Hello对象。

public class Hello{
public void sayHello(){
System.out.println("hello");
}
}
public class Test{
Hello hello = new Hello();
public void test(){
hello.sayHello();
}
}

但是控制反转的是Spring框架已经把这个Hello对象创建好了,保存在框架里面,当Test需要用到Hello对象的时候,Test对象只需要向Spring框架说我要Hello对象,Spring就会给他一个Hello对象,这个过程就是依赖注入。

Spring IoC容器的设计


而Spring提供的最基本的BeanFactory的实现类是DefaultListableBeanFactory,这个类是也是实现ApplicationContext接口的一些高级容器的基础容器。以XmlBeanFactory实现类为例的编程式IoC容器,这个就是XML配置形式的IoC容器的初始化过程。

//获取定义了bean信息的xml配置文件位置
ClassPathResource res = new ClassPathResource("bean.xml");
//创建一个BeanFactory
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//创建一个BeanDefinition的读取器,并设置把读取到的信息加载到BeanFactory
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
//实现xml配置文件的信息读取,加载和注册BeanDefinition整个过程
reader.loadBeanDefinition(res);

IoC容器的初始化过程-Resource定位过程

这个定位过程实际上就是

ClassPathResource res = new ClassPathResource("bean.xml");

以FileSystemXmlApplicationContext为例,写一个Debug过程:
在容器初始化的时候会调用FileSystemXmlApplicationContext的构造方法,

public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
//指定自己的双亲IoC容器
super(parent);
//指定包含BeanDefinition信息的配置文件所在路径
setConfigLocations(configLocations);
//刷新容器,实现创建容器、载入、实例化对象的过程
if (refresh) {
refresh();
}
}

接着进入上面代码的refresh()方法
- AbstractApplicationContext.refresh()
- AbstractApplicationContext.obtainFreshBeanFactory()
- AbstractRefreshableApplicationContext.refreshBeanFactory()

//AbstractRefreshableApplicationContext.refreshBeanFactory()
protected final void refreshBeanFactory() throws BeansException {
//如果存在BeanFactory,关闭并销毁
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//创建一个DefaultListableBeanFactory的BeanFactory,并初始化
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
//载入BeanDefinition的信息,在本类提供了这个方法的抽象
//在AbstractXmlApplicationContext子类重写了,实际是调用了子类的这个方法
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}

接着代码里面的loadBeanDefinitions(beanFactory)继续Debug
- AbstractXmlApplicationContext.loadBeanDefinitions()
- AbstractBeanDefinitionReader.loadBeanDefinitions(String… locations)

//同是在AbstractBeanDefinitionReader里面的
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}

if (resourceLoader instanceof ResourcePatternResolver) {
// 调用DefaultResourceLoader的getResource完成具体的Resource定位
try {
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
int loadCount = loadBeanDefinitions(resources);
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// 根据URL实现单个资源文件的定位
Resource resource = resourceLoader.getResource(location);
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}
  • PathMatchingResourcePatternResolver.getResources()
  • DefaultResourceLoader.getResource()
    接下来步入进去看一下的实现
public Resource getResource(String location) {
Assert.notNull(location, "Location must not be null");
//处理带有classpath的Resource
for (ProtocolResolver protocolResolver : this.protocolResolvers) {
Resource resource = protocolResolver.resolve(location, this);
if (resource != null) {
return resource;
}
}
if (location.startsWith("/")) {
return getResourceByPath(location);
}
else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
}
else {
try {
// 处理带有URL表示的Resource
URL url = new URL(location);
return new UrlResource(url);
}
catch (MalformedURLException ex) {
//处理既不是classpath,也不是URL标识的资源,调用接口的getResourceByPath(location)方法,通常在子类实现
//此时此方法在FileSystemXmlApplicationContext.getResourceByPath(location)实现了
return getResourceByPath(location);
}
}
}
  • FileSystemXmlApplicationContext.getResourceByPath(location)
protected Resource getResourceByPath(String path) {
if (path != null && path.startsWith("/")) {
path = path.substring(1);
}
return new FileSystemResource(path);
}

最终返回一个实现了Resource接口的实例,完成了Resource资源的定位,接下来就是BeanDefinition的载入了。

BeanDefinition的载入和解析

继续从FileSystemXmlApplicationContext的构造器开始

public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException
  • AbstractApplicationContext.refresh()
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
//这里是在子类中启动refreshBeanFactory的地方
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
/*省略下部的代码,主要研究obtainFreshBeanFactory()*/
}
}
  • AbstractApplicationContext.obtainFreshBeanFactory()
  • AbstractRefreshableApplicationContext.refreshBeanFactory()
protected final void refreshBeanFactory() throws BeansException {
//如果存在BeanFactory,关闭并销毁
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//创建一个DefaultListableBeanFactory的BeanFactory,并初始化
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
//载入BeanDefinition的信息,在本类提供了这个方法的抽象
//在AbstractXmlApplicationContext子类重写了,实际是调用了子类的这个方法
/*启动对BeanDefinition的载入*/<
20000
/span>
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
  • AbstractXmlApplicationContext.loadBeanDefinitions()
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//创建一个XmlBeanDefinitionReader并设置把读取到的信息设置在beanFactory
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 配置XmlBeanDefinitionReader的读取环境和资源加载器
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
/*启动Bean定义信息载入的过程*/
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
//以Resource形式获取配置文件位置
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
//以String形式获取配置文件位置
String[] configLocations = getConfigLocations();
if (configLocations != null) {
/*接着进入这里分析*/
reader.loadBeanDefinitions(configLocations);
}
}
protected Resource[] getConfigResources() {
return null;
}

-AbstractBeanDefinitionReader.loadBeanDefinitions()

public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
try {
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
/*前面是定位,此处是加载BeanDefinition*/
int loadCount = loadBeanDefinitions(resources);
/*省略此处代码*/
}
catch (IOException ex) {
/*省略此处代码*/
}
}
else {
/*省略此处代码*/
}
return loadCount;
}
}
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
//如果Resource为空则返回
//遍历所有Resource再载入BeanDefinition
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
for (Resource resource : resources) {
counter += loadBeanDefinitions(resource);
}
return counter;
}
  • XmlBeanDefinitionReader.loadBeanDefinitions()
//调用入口
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
//载入XML形式的BeanDefinition的地方
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());
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
//这里得到XML文件,并得到InputSource准备进行读取
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();
}
}
}
  • XmlBeanDefinitionReader.doLoadBeanDefinitions()
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//获取XML文件的Document对象
Document doc = doLoadDocument(inputSource, resource);
/*启动对BeanDefinition的载入过程,从这里进去*/
return registerBeanDefinitions(doc, resource);
}
/*省略异常代码*/
}
  • XmlBeanDefinitionReader.registerBeanDefinitions()
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//创建BeanDefinitionDocumentReader对XML的BeanDefinition进行解析,
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
/*具体的解析过程从这里进去*/
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
  • DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions()
  • DefaultBeanDefinitionDocumentReader.parseBeanDefinitions()
  • DefaultBeanDefinitionDocumentReader.parseDefaultElement()
  • DefaultBeanDefinitionDocumentReader.processBeanDefinition()
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
/*解析BeanDefinition并用BeanDefinitionHolder封装BeanDefinition、beanName等信息,我们要研究载入过程,从这里进去*/
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 向容器注册BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 注册完成后发送消息
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
  • BeanDefinitionParserDelegate.parseBeanDefinitionElement()
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
/*省略代码,这部分主要取得再<bean>元素中定义的id、name和aliase等属性*/
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
/*这个方法会引发对Bean元素的详细解析,从这里进去研究*/
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
/*省略后面的代码*/
}
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
//这里读取<bean>中定义的信息,载入到BeanDefinition中,不涉及实例化的过程
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
//获取类名
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
try {
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
//新建BeanDefinition对象,为Bean定义信息的载入做准备
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//对当前Bean的元素属性进行解析,设置Description信息
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//对各种<bean>元素进行解析
parseMetaElements(ele, bd);
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析<bean>构造函数设置
parseConstructorArgElements(ele, bd);
//解析<bean>的property设置
parsePropertyElements(ele, bd);
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
/*省略异常代码*/
finally {
this.parseState.pop();
}
return null;
}

这个就是解析BeanDefinition的具体过程,具体的property参数或者是Constructor参数解析可以深入研究parseConstructorArgElements(ele, bd)和parsePropertyElements(ele, bd)。

BeanDefinition在IoC容器中的注册

在DefaultListableBeanFactory类中使用一个Map集合保存beanName->BeanDefinition

/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);

从DefaultBeanDefinitionDocumentReader.processBeanDefinition()继续研究

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
/*注册BeanDefinition到IoC容器,我们从这里开始*/
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
  • BeanDefinitionReaderUtils.registerBeanDefinition()
  • DefaultListableBeanFactory.registerBeanDefinition()
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
//检查是否有相同名字的BeanDefinition已经在容器中注册
//如果有并且不能覆盖,则抛出异常
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
//如果是这个已经初始化结束,后来向容器中追加
//那么注册过程需要synchronized,保证数据的一致性
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// 如果容器继续处于启动阶段,那么就可以直接注册
/*这是正常注册BeanDefinition的过程,把Bean的名字存入到BeanDefinitionNames同时把beanName作为Map的Key,
把beanDefinition作为value存入到IoC容器持有的beanDefinitionMap中去*/
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}

if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}

至此,完成了Resource的定位,BeanDefinition的载入和注册。

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: