使用弹簧如何实现加载Bean

  介绍

本篇文章给大家分享的是有关使用弹簧如何实现加载豆,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

<强> 1定义Bean的方式

常见的定义Bean的方式有:

通过xml的方式,例如:

& lt; Bean id=癲ictionaryRelMap"类=癹ava.util.HashMap"/祝辞

通过注解的方式,在课堂上使用@ component等注解,例如

@ component   公开课xxxServicer {   …   }

通过在@ configuration类下的@ bean的方式,例如

@ configuration   公开课xxxConfiguration {   @ bean   公共myBean myBean () {   返回新myBean ();   }   }

虽然这三种定义Bean的方式不一样,对应的处理细节也不一样,但是从大的逻辑上来看,都是一样。主要的流程如下图:最关键的就是问题就是这么去找到定义Bean的方式,然后生成BeanDefinition后注册到弹簧上下文中,由弹簧自动创建Bean的实例。

使用弹簧如何实现加载Bean

<强> 2 BeanDefinition

BeanDefinition是一个接口,用来描述一个Bean实例,例如是单例还是原型,属性的值是什么,构造函数的参数是什么等。简单来说,通过一个BeanDefinition我们就可以完成一个Bean实例化。BeanDefinition及其主要的子类:

使用弹簧如何实现加载Bean

下面简单说一下各个子类:

    <李> RootBeanDefinition和ChildBeanDefinition:这2个BeanDefinition是相对的关系,自Spring 2.5出来以后,已经被GenericBeanDefinition代替,因为这样强迫我们在编写代码的时候就必须知道他们之间的关系。 <李> GenericBeanDefinition:相比于RootBeanDefinition和ChildBeanDefinition在定义的时候就必须硬编码,GenericBeanDefinition的优点可以动态的为GenericBeanDefinition设置父母。 <李> AnnotatedBeanDefinition:看名字就是知道是用来读取通过注解定义。

<强> 3通过xml文件定义Bean

通过xml定义Bean是最早的春天定义Bean的方式,因此,怎么把xml标签解析为BeanDefinition(),入口是在org.springframework.beans.factory.xml.XmlBeanDefinitionReader这个类,但是实际干活的是在org.springframework.beans.factory.xml.BeanDefinitionParserDelegate。代码很多,但实际逻辑很简单,就是解析春天定义的& lt; bean>& lt; property>等标签。

<强> 4通过@ component等弹簧支持的注解加载Bean

如果要使用@ component等注解定义,一个前提条件是:有& lt;上下文:component-scan/祝辞或者@ComponentScan注解。但这2个方式还是有一点点区别:

<强> 4.1 & lt;上下文:component-scan/祝辞

由于& lt;上下文:component-scan/祝辞是一个xml标签,因此是在解析xml,生成的类org.springframework.context.annotation。ComponentScanBeanDefinitionParser,关键代码:

@Override   公共BeanDefinition解析(元素元素,ParserContext ParserContext) {//获取基础包标签   字符串basePackage=element.getAttribute (BASE_PACKAGE_ATTRIBUTE);   .getEnvironment basePackage=parserContext.getReaderContext () () .resolvePlaceholders (basePackage);   String [] basePackages=StringUtils.tokenizeToStringArray (basePackage,   ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);//实际处理类是ClassPathBeanDefinitionScanner   ClassPathBeanDefinitionScanner扫描仪=configureScanner (parserContext元素);//扫描basePackage下所有的类,如果有@ component等标签就是注册到Spring中   Setbeandefinition=scanner.doScan (basePackages);   registerComponents (parserContext.getReaderContext ()、beandefinition元素);   返回null;   }

<强> 4.2 @ComponentScan

注解对应生成的类是org.springframework.context.annotation。ComponentScanAnnotationParser其实最后实际干活的还是ClassPathBeanDefinitionScanner这个.ComponentScanAnnotationParser类的生成是伴随着@ configuration这个注解处理过程中(意思说@ComponentScan必须和@ configuration一起使用)。而处理@ configuration其实是org.springframework.context.annotation.ConfigurationClassPostProcessor。是不是感觉有点绕。

其实简单来说,在处理@ configuration的时候发现有@ComponentScan注解,就会生成ComponentScanAnnotationParser去扫描@ component注解

<强> 4.3 ClassPathBeanDefinitionScanner

上面说到了,无论注解还是标签的方式,最后都会交给ClassPathBeanDefinitionScanner这个类来处理,这个类做的就是1。扫描basePackage下所有类,如果有@ component等注解,读取@ component相关属性,生成ScannedGenericBeanDefinition,注册到Spring中。

使用弹簧如何实现加载Bean