Spring 总结

本文深入剖析了Spring框架的核心功能,包括BeanFactory、BeanDefinition的解析、对象初始化和依赖注入、AOP的实现原理以及Spring事务管理。文章详细介绍了Spring如何从XML配置解析到BeanDefinition,再到Bean的创建和初始化过程,以及AOP的代理对象创建和调用流程。同时,还探讨了SpringMVC的初始化与Servlet 3.0的关系,以及Spring在实际应用中的最佳实践。
摘要由CSDN通过智能技术生成

简介

Spring是Java程序员日常开发中最长应的应用框架之一,它是如此的流行甚至对Java语言本身的发展都起到了推动作用,目前Spring可以说是Java后端开发的事实标准。Spring的优点可以总结如下:

  • Spring的两个最核心功能是IoC和Aop,为模块解耦合提供了基础支持;
  • 基于Aop实现的声明式缓存和声明式事务大大简化了代码逻辑;
  • 基于Spring的SpringMVC为快速接入JavaEE提供支持;
  • Spring的test模块解决了应用程序的单元测试问题;
  • Spring可以与很多优秀的框架集成,可以说跟谁都行有一腿;
  • 基于Spring构建的SpringBoot、SpringCloud使得Spring在微服务领域迎来了第二个春天;

BeanFactory

在刚开始接触Spring的时候,有人说Spring就是一个生产bean对象的工厂,底层实际上就是一个Map,直到现在对此也非常认同,Spring是一个Map,但绝不仅仅是一个Map,下面先看看Spring的BeanFactory结构
在这里插入图片描述
从图中的类名称可以看出,Spring从BeanFactory扩展出了具有不同能力的BeanFactory,当然这还不包含ApplicationContext,所以我个人对Spring的理解是它在HashMap的基础上扩展处理成百上千个特性,这些特性让Spring成为了一个优秀的框架产品。

如果把Spring当成是一个生产Bean的工厂,那么这个Bean工厂上产Bean的原材料就是BeanDefinition,从名字上就可以看出来,BeanDefinition是定义Bean的Bean,也就是说BeanDefinition封装了每一个能够被Spring管理的Bean的元数据,例如类型、依赖、属性、初始化方法等
在这里插入图片描述
从Spring中获取一个bean对象的主流程包括两步

  • 加载配置文件,从中解析出BeanDefinition
  • 调用getBean(beanName)触发Bean的初始(从BeanDefinition到Bean)

Spring源码-初始化BeanDefinition

这里主要说说xml的解析,主要原因是相比注解的方式更加简单,以ClasspathXmlApplication为例,下面进入源码部分。
在这里插入图片描述
整个Spring初始的入口是ClasspathXmlApplication的构造方法

ClasspathXmlApplication
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
		throws BeansException {                                                                            
                                                                                                           
	super(parent);                                                                                         
	setConfigLocations(configLocations);                                                                   
	if (refresh) {    
	    //入口在这里                                                                                     
		refresh();                                                                                         
	}                                                                                                      
} 
@Override                                   
protected Resource[] getConfigResources() { 
	return this.configResources;            
}                                                                     

AbstractApplicationContext.java
@Override
public void refresh() throws BeansException, IllegalStateException {
	ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
}

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { 
	refreshBeanFactory();
}

AbstractRefreshableApplicationContext.java
@Override
protected final void refreshBeanFactory() throws BeansException { 
    /**
      这里创建了BeanFactory的实例 - DefaultListableBeanFactory
  		所以说,我们开发中用到的ApplicationContext是BeanFactory的封装,
  		在BeanFactory的基础上提供了很多额外的功能,例如
  		事件发布与监听、组件扫描、国际化等
     **/
	DefaultListableBeanFactory beanFactory = createBeanFactory();
	//从这里开始加载配置文件,注册BeanDefinition到BeanFactory
	loadBeanDefinitions(beanFactory);
}

AbstractXmlApplicationContext.java implements ResourceLoader 
 */
 @Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { 
        //创建一个专门从Xml中读取BeanDefinition的XmlBeanDefinitionReader
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
		beanDefinitionReader.setResourceLoader(this);
		loadBeanDefinitions(beanDefinitionReader);
}

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
        /**
			当前类中的getConfigResources方法被ClasspathXmlApplicationContext重写了,
			所以这里调用的是ClasspathXmlApplicationContext中的方法
       */
		Resource[] configResources = getConfigResources();
		reader.loadBeanDefinitions(configResources);
 }
protected Resource[] getConfigResources() {
		return null;
}
                           
AbstractBeanDefinitionReader.java
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException { 
	loadBeanDefinitions(resource);
}         
XmlBeanDefinitionReader.java
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(new EncodedResource(resource));
}
/**
   这里是解析的核心逻辑
*/
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
	//将配置文件转换成了InputStream流对象
	InputStream inputStream = encodedResource.getResource().getInputStream();
	return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}                    


protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) }{
    //从流对象得到Document对象
	Document doc = doLoadDocument(inputSource, resource);
    return registerBeanDefinitions(doc, resource);
}   

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    //创建一个从Document中获取BeanDefinition的Reader
	BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
	documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
 }                  

DefaultBeanDefinitionDocuemntReader.java
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { 
	doRegisterBeanDefinitions(root);
}  

protected void doRegisterBeanDefinitions(Element root) { 
	parseBeanDefinitions(root, this.delegate);
}

这里就开始解析Elemnent对象了
在这里插入图片描述

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		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)) {
					   //如果是spring默认的标签,就有spring内核自己来解析,例如beans、bean、<property>等等
						parseDefaultElement(ele, delegate);
					}
					else {
					    //如果是其他模块的标签或自定义的标签,例如 <aop:xxx>   <tx:xxx> 
					    //就通过对应的xml名称空间,从spring.handlers中找到对应的NamespaceHandler
					    //再由NamespaceHandler设置的parser进行解析
					    //这也是其他框架与spring进行集成的一个方式,例如dubbo的DubboNamespaceHandler就是用来解析<dubbo:xxx>的
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
		String namespaceUri = getNamespaceURI(ele);
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}

最后实际上就是将解析出来的BeanDefinition通过BeanDefinitionRegistry提供的接口能力注册到DefaultListableBeanFactory中
实际上DefaultListableBeanFactory实现了BeanDefinitionRegistry接口,而最终BeanDefinition对象就会被添加到DefaultListableBeanFactory的
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
这个Map中。

下面我们看看BeanDefinition
在这里插入图片描述
可以说一目了然,我们所有的配置信息最终都会被解析到BeanDefinition中,Spring在创建Bean实例时,就会根据这些信息来执行不同的逻辑。

从这段逻辑中其实还能学点很多关于代码设计的知识点,比如在解析xml的时候通过BeanDefinitionReader/XmlBeanDefinitionDocumentReader等层层委托,遵循了面向对象设计原则的单一职责原则,再比如大量使用模板模式实现子类的灵活扩展。

Spring源码-对象初始化&依赖注入

前面讲了注册BeanDefinition的过程,有了创建Bean的原材料,接下来就是创建Bean对象了。

在Spring中创建Bean对象的入口有两个,一个是调用getBean()方法从容器中获取Bean对象,另外一个就是在Spring容器初始化的时候,会默认对单例对象进行初始化

AbstractApplicationContext.java
@Override
public void refresh() throws BeansException, IllegalStateException { 

    // 这里会对非懒加载的bean进行实例化,实际上也是调用getBean,所以
    // 触发bean实例化的入口就是getBean,
	// Instantiate all remaining (non-lazy-init) singletons.
	finishBeanFactoryInitialization(beanFactory);
}

下面来看一下getBean方法的逻辑

AbstractApplicationContext.java
@Override
	public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
		assertBeanFactoryActive();
		/**
			这里调用的是DefaultListableBeanFactory的getBean方法
			前面说过,ApplicationContext实际上是对BeanFactory
			的再次封装,此处还是基于BeanFactory来实现IoC容器
			所以这里也就很容易理解了
		*/
		return getBeanFactory().getBean(name, requiredType);
	}

AbstractBeanFactory中的doGetBean是Bean对象初始化的核心方法,化繁为简,以单例对象的创建过程为例来说明

protected <T> T doGetBean(
			final String name, final C
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值