`
wang4674890
  • 浏览: 89374 次
  • 性别: Icon_minigender_2
  • 来自: 厦门
社区版块
存档分类
最新评论

spring 加载bean过程源码简易解剖

阅读更多
这一篇主要是讲用载入bean的过程。其实就是IOC.低调 低调。。

我把重要的都挑出来了。一步步往下看就明白spring载入bean.xml里面bean的原理 。
感觉像候杰的 MFC深入浅出,哈哈。

观看规则

接下 表示下一层代码。
接上 表示最近上面要调用的代码的详细部分。





public class XmlBeanFactory extends DefaultListableBeanFactory {

        //新建一个bean分析器,把this注册到里面是因为,在分析器解析好一个bean时,可以立即用这个this里的注册方法去保存bean,往下看就明白。任何bean到最后都是保存在XmlBeanFactory里的(其实是DefaultListableBeanFactory)。 

	private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

	public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {

		super(parentBeanFactory);
                //载入xml文件
		this.reader.loadBeanDefinitions(resource); //往下->
	}
}

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
     //接上
     public int loadBeanDefinitions(Resource resource) throws BeansException {

		InputStream is = null;

		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

		factory.setValidating(this.validating);

		DocumentBuilder docBuilder = factory.newDocumentBuilder();

		docBuilder.setErrorHandler(this.errorHandler);

		if (this.entityResolver != null) {
		    docBuilder.setEntityResolver(this.entityResolver);
		}
		is = resource.getInputStream();
//用Xerces解析xml,生成dom
		Document doc = docBuilder.parse(is);
//registerBeanDefinitions分析dom
		return registerBeanDefinitions(doc, resource); //往下

	}

//接上
        public int registerBeanDefinitions(Document doc, Resource resource) throws BeansException {

		XmlBeanDefinitionParser parser = (XmlBeanDefinitionParser) BeanUtils.instantiateClass(this.parserClass);
//这个parserClass 是  DefaultXmlBeanDefinitionParser.class
		return parser.registerBeanDefinitions(this, doc, resource); //往下->

	}

}

public class DefaultXmlBeanDefinitionParser implements XmlBeanDefinitionParser {
//明显就是bean.xml里面出现的很熟悉的标签,说明已经快到底层类了
       

	public static final String AUTOWIRE_BY_NAME_VALUE = "byName";
	public static final String AUTOWIRE_BY_TYPE_VALUE = "byType";
	public static final String DEFAULT_LAZY_INIT_ATTRIBUTE = "default-lazy-init";
	public static final String DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE = "default-dependency-check";
	public static final String DEFAULT_AUTOWIRE_ATTRIBUTE = "default-autowire";
	public static final String NAME_ATTRIBUTE = "name";
	public static final String ALIAS_ATTRIBUTE = "alias";
	public static final String BEAN_ELEMENT = "bean";
	public static final String ID_ATTRIBUTE = "id";
	public static final String PARENT_ATTRIBUTE = "parent";
	public static final String CLASS_ATTRIBUTE = "class";
	public static final String SINGLETON_ATTRIBUTE = "singleton";
	public static final String LAZY_INIT_ATTRIBUTE = "lazy-init";
	public static final String AUTOWIRE_ATTRIBUTE = "autowire";
	//...
   //接上
   public int registerBeanDefinitions(BeanDefinitionReader reader, Document doc, Resource resource) throws BeanDefinitionStoreException {

		this.beanDefinitionReader = reader;
		this.resource = resource;;
		Element root = doc.getDocumentElement();
		//...

//这里准备开始正式解析bean
		int beanDefinitionCount = parseBeanDefinitions(root);//往下->
//这个beanDefinitionCount 就是解析出了多少个<bean></bean>
		
//...
		return beanDefinitionCount;
	}

protected int parseBeanDefinitions(Element root) throws BeanDefinitionStoreException {
//Xerces开始循环找<bean>标签
		NodeList nl = root.getChildNodes();
		int beanDefinitionCounter = 0;
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element) {
				Element ele = (Element) node;
				if // ...
//..
				else if (BEAN_ELEMENT.equals(node.getNodeName())) {//这里是重点,开始解析bean
					beanDefinitionCounter++;
//分两步走,看下面详解。1.先把bean放到BeanDefinitionHolder
					BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele);//往下 1.->
//2.然后XmlBeanFactory去注册
					BeanDefinitionReaderUtils.registerBeanDefinition(
							bdHolder, this.beanDefinitionReader.getBeanFactory()); //往下 2. ->
				}
			}
		}
		return beanDefinitionCounter;
	}

//接上1. 哈哈,下面是第一步,是正常解析bean,在同一个类中
protected BeanDefinitionHolder parseBeanDefinitionElement(Element ele) throws BeanDefinitionStoreException {
		//...
                //下面可以看到其实最底层的解析bean在同一个类的parseBeanDefinitionElement方法里。因为spring把bean封装成BeanDefinition 再把BeanDefinition 封装成BeanDefinitionHolder 

		BeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName);//往下

//...
		return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
	}

//接上 , 这个方法很长,毕竟<bean>里attribute很多。
  protected BeanDefinition parseBeanDefinitionElement(Element ele, String beanName) throws BeanDefinitionStoreException {
		try {
                        //下面解析<bean>里的<property>,这个我不分析了。
			MutablePropertyValues pvs = parsePropertyElements(ele, beanName);
                        //将BeanDefinition封装成AbstractBeanDefinition 
			AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(
					className, parent, cargs, pvs, this.beanDefinitionReader.getBeanClassLoader());
			//...		
			return bd;
		}
		catch (/*...*/)
                   //...

		}
	}


}
//bean解析部分到此结束。。。。


//接上2. 这里是第二部,注册部分,回到上面注释里的分两部走这里。
public class BeanDefinitionReaderUtils {
  public static void registerBeanDefinition(
			BeanDefinitionHolder bdHolder, BeanDefinitionRegistry beanFactory) throws BeansException {

		
//beanFactory就是XmlBeanFactory,其实是它的父类 DefaultListableBeanFactory在执行registerBeanDefinition


		beanFactory.registerBeanDefinition(bdHolder.getBeanName(), bdHolder.getBeanDefinition()); //往下
//...
	}

}

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
    implements ConfigurableListableBeanFactory, BeanDefinitionRegistry {
  
	/** Whether to allow re-registration of a different definition with the same name */
	private boolean allowBeanDefinitionOverriding = true;

	/** Map of bean definition objects, keyed by bean name */
//下面是真正藏bean的地方,其实是个Map,跟我预想的一样。
	private final Map beanDefinitionMap = new HashMap();
//下面List可能是给bean的名字做个索引,这是我的初步猜想。
	/** List of bean definition names, in registration order */
	private final List beanDefinitionNames = new ArrayList();
  //接上
  public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
//...
  Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
		if (oldBeanDefinition != null) {
//根据allowBeanDefinitionOverriding这个变量来决定在bean.xml里的bean万一有同名的情况下否覆盖,因为allowBeanDefinitionOverriding默认是true,所以覆盖。
			if (!this.allowBeanDefinitionOverriding) {
				throw new BeanDefinitionStoreException(...);
			}
			else {
				//...只用注释提醒相同bean将要被覆盖了
			}
		}
		else {
                        //索引List里加上这个bean名字
			this.beanDefinitionNames.add(beanName);
		}
                //将bean藏在map里。用名字来索引。
		this.beanDefinitionMap.put(beanName, beanDefinition);
		
	}
//...

}
//结束


可以看到其实spring就是把bean.xml解析到一个map里。
至于获取bean的方法 ,我不用说大家都知道了,到了底层就是 map.get("bean name");
万流归终啊。。。。
分享到:
评论

相关推荐

    springBean加载过程源码解析文档,附有代码类名和行数

    Spring Bean 加载过程源码解析文档 Spring Bean 加载过程是 Spring 框架中最核心的部分之一,涉及到 ApplicationContext 的初始化、Bean 的加载和注册等过程。在 Spring Boot 应用程序中,SpringApplication 负责...

    详解Spring简单容器中的Bean基本加载过程

    Spring 简单容器中的 Bean 基本加载过程 Spring 框架是 Java 企业级应用程序的核心框架之一,它提供了一个 IOC(Inverse of Control,控制反转)容器,用于管理应用程序中的对象。Spring IOC 容器的核心是 ...

    Spring bean 动态注册,jar包热替换

    Spring bean 一般通过配置文件和注解进行加载,如果要实现jar或class文件,动态实现spring bean 的动态加载,并通过UrlClassLoader完成jar和class文件的加载。可以实现jar的热替换。spring的bean动态加载则需要对...

    Spring加载Bean: AbstractBeanFactory.xmind

    Spring加载Bean: AbstractBeanFactory.xmind

    spring bean的源码

    Spring 大量引入了Java 的Reflection机制,通过动态调用的方式避免硬编码方式的约束,并在此基础上建立了其核心组件...org.springframework.beans包中包括了这些核心组件的实现类,这里就提供了该包中的源码。

    spring的bean加载顺序样例项目

    在"spring的bean加载顺序样例项目"中,我们可以通过分析和实验来深入理解这一主题。下面将详细阐述Spring Bean的加载顺序以及相关知识点。 1. **Bean的定义与作用域** - Spring中的Bean是在`beans.xml`或Java配置...

    Spring Bean创建初始化流程.docx

    在Spring框架中,Bean的创建和初始化是IoC(Inversion of Control)容器的核心功能,这一过程涉及到多个步骤。以下是对Spring Bean创建初始化流程的详细解释: 1. **初始化ApplicationContext**: 开始时,通过`...

    spring 重新动态加载数据库或xml中的bean,可以不用重启tomcat

    spring 重新动态加载数据库或xml中的bean,可以不用重启tomcat

    spring源码bean扫描过程

    spring源码bean生命周期doScan扫描过程图

    spring运行过程中动态注册bean

    在Spring框架中,动态注册Bean是一项非常实用的功能,它允许我们在应用运行时向Spring容器添加新的Bean定义。这种能力在很多场景下都是极其有用的,比如根据不同的环境配置加载不同的服务实现,或者在运行时根据某些...

    详解Spring 中如何控制2个bean中的初始化顺序

    因此,在使用 DependsOn 注解时,需要了解 Spring 中 bean 的加载过程,以免出现错误。 其他实现方式 除了上述两种方式外,还有其他方式可以控制 2 个 bean 的初始化顺序。例如,可以使用 Spring 的 @Order 注解来...

    spring bean XML配置入门

    一旦XML配置加载到Spring容器中,容器将根据配置创建Bean实例,并按照定义进行初始化、依赖注入,最后完成Bean的生命周期管理。 10. **实践操作**: 在实际开发中,我们可以使用Eclipse的Spring插件来简化Bean...

    Spring Bean 加载顺序 .

    让我们详细探讨Spring Bean加载顺序的各个环节。 1. **配置源解析**: Spring支持多种配置方式,包括XML、Java配置类(@Configuration)、注解(@Component、@Service等)以及通过@ConfigurationProperties处理...

    Spring Bean重复执行两次(实例被构造两次)问题分析

    在Spring容器初始化时,它会根据配置加载Bean的定义,并根据需要创建Bean实例。Bean的生命周期大致分为以下几个阶段:构造、初始化、正常使用、销毁。如果一个Bean被创建了两次,那么可能是在构造或初始化阶段出现了...

    spring bean的生命周期

    - **XML配置**:在传统的Spring应用中,Bean的定义通常写在XML配置文件中,如`springbean-xml`中的配置。 - **注解配置**:使用`@Component`,`@Service`,`@Repository`和`@Controller`注解标记类,配合`@...

    spring 5.2.9 07 源码分析-spring的bean工厂准备工作 测试用例

    在源码分析过程中,我们关注的重点是Bean的加载和解析阶段。这涉及到`BeanDefinitionReader`和`BeanDefinitionRegistry`。`BeanDefinitionReader`用于读取Bean定义,如XML、Java注解或Groovy脚本等形式,将其转化为`...

    spring 获取bean

    spring 获取bean spring 获取bean spring 获取bean spring 获取bean spring 获取bean spring 获取bean spring 获取bean spring 获取bean

    Spring源码深度解析第二版

    XmlBeanFactory是Spring框架的容器实现之一,主要用于加载和管理Bean。XmlBeanFactory的基础实现主要包括了加载Bean、实例化Bean和依赖注入等。 2.5.1 自己直文件封装 XmlBeanFactory的自己直文件封装主要包括了...

    Spring多种加载Bean方式解析

    本篇文章主要介绍了Spring多种加载Bean方式解析,通过对Bean加载方式的详细解析,了解Spring中的Bean加载机制。 定义Bean的方式 在Spring中,定义Bean的方式有多种,常见的定义Bean的方式有三种: 1. 通过xml的...

    Spring 源码分析(Bean的初始化)

    在Spring框架中,Bean的初始化是一个至关重要的过程,它涉及到从XML配置文件或者注解中读取Bean的定义,解析并构建Bean实例。本篇文章主要分析了Spring如何通过`ClassPathXmlApplicationContext`来启动和初始化Bean...

Global site tag (gtag.js) - Google Analytics