码迷,mamicode.com
首页 > 编程语言 > 详细

《Spring技术内幕》笔记-第二章 IoC容器的实现

时间:2017-06-04 14:41:13      阅读:275      评论:0      收藏:0      [点我收藏+]

标签:事务   clean   npos   pretty   stream   pre   into   ifreq   runtime   

简单介绍

1,在Spring中,SpringIoC提供了一个主要的JavaBean容器。通过IoC模式管理依赖关系。并通过依赖注入和AOP切面增强了为JavaBean这样子的POJO提供事务管理,生命周期管理等功能。

2,Spring IoC的设计中,主要包括两个基本的容器系列:

    -1,BeanFactory系列。该序列实现了容器的基本功能。

    -2。ApplicationContext应用上下文。


Spring IoC容器的设计

1,例如以下图,IoC容器的接口设计图。

    

技术分享

2,简单介绍

    -1,从BeanFactory到HierarchicalbeanFactory再到ConfigurableBeanFactory是一条基本的BeanFactory设计路径。BeanFactory定义了基本的IoC容器接口。

HierarchicalBeanFactory接口继承了BeanFactory接口,并再其基础上添加了getParentBeanFactory()接口功能,使得BeanFactory具备双亲IoC管理功能。ConfigurableBeanFactory主要定义了对BeanFactory的配置功能。


    -2。以ApplicationContext为核心的接口设计。

BeanFactory的应用场景

    BeanFactory是最主要的IoC容器。


    用户在使用容器的时候能够通过&符来获取FactoryBean本身。FactoryBean跟普通Bean不同。通过BeanFactory类的getBean方法直接获取到的并非该FactoryBean的实例,而是 该FactoryBean中方法getObject返回的对象。

但我们能够通过其他途径获取到该FactoryBean的实例。方法就是在通过 getBean方法获取实例时在參数name前面加上“&”符号就可以。

    

    1. String FACTORY_BEAN_PREFIX = "&";


    1。BeanFactory的主要接口,以及其作用例如以下:

    -1。容器推断是否包括指定名字的bean。

    1. boolean containsBean(String name);

    -2,推断指定的bean是否是prototype类型。

    1. boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    -3。推断指定的bean是否是singleton。

    1. boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    -4,推断指定的bean是否与给定类型相匹配。

    1. boolean isTypeMatch(String name, Class<?

      > targetType) throws NoSuchBeanDefinitionException;

    -5,获取指定Bean的类型。

    1. Class<?

      > getType(String name) throws NoSuchBeanDefinitionException;

    -6。指定bean的全部别名。

    1. String[] getAliases(String name);

2,BeanFactory的容器设计原理。

    BeanFactory接口提供了使用IoC的规范,而且Spring实现了一系列容器的实现供开发者使用。

以XmlBeanFactory为例。例如以下为XmlBeanFactory的继承结构图。

技术分享


下面是XmlBeanFactory的代码,在Spring 4中。该类已经不推荐被使用了。

    1. @Deprecated

    2. @SuppressWarnings({"serial", "all"})

    3. public class XmlBeanFactory extends DefaultListableBeanFactory {

    1. private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

    1. /**

    2. * 通过给定的资源创建一个XmlBeanFactory实例。

    3. */

    4. public XmlBeanFactory(Resource resource) throws BeansException {

    5. this(resource, null);

    6. }

    1. /**

    2. * Create a new XmlBeanFactory with the given input stream,

    3. * which must be parsable using DOM.

    4. */

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

    6. super(parentBeanFactory);

    7. this.reader.loadBeanDefinitions(resource);

    8. }

    1. }

    该类继承了DefaultListableBeanFactory类。DefaultListableBeanFactory该类实现一个最为基础的IoC容器。

    例如以下是一个简单的使用方法举例:


    1. ClassPathResource re = new ClassPathResource("bean.xml");

    2. DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

    3. XmlBeanDefinitionReader xdr = new XmlBeanDefinitionReader(beanFactory);

    4. xdr.loadBeanDefinitions(re);

    5. System.out.println(xdr.getRegistry());


ApplicationContext的应用场景

   1。 ApplicationContext在BeanFactory的基础上添加了非常多新的特性:

    -1。支持不同的信息源。ApplicationContext扩展了MessageSource接口,这些为国际化提供服务。


    -2,訪问资源。对ResourceLoader和Resource的支持。能够从不同的地方获取到资源。


    -3。支持应用事件。

继承ApplicationEventPublisher,从而引入的事件机制。

与Bean的生命周期结合,方便管理Bean。


    -4,在ApplicationContext添加附加服务。

    2,ApplicationContext设计原理,以FileSystemApplicationContext为例。


    1. public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)

    2. throws BeansException {

    1. super(parent);

    2. setConfigLocations(configLocations);

    3. if (refresh) {

    4. refresh();

    5. }

    6. }


    在实例化该应用中,调用了AbstractApplicationContext的refresh方法。该方法是IoC容器启动的主要方法。

    另一个主要方法是:


    1. @Override

    2. protected Resource getResourceByPath(String path) {

    3. if (path != null && path.startsWith("/")) {

    4. path = path.substring(1);

    5. }

    6. return new FileSystemResource(path);

    7. }

该方法通过FileSystemResource获取资源路径。

IoC容器的初始化过程

    简单来说IoC的初始化是由AbstractApplicationContext的refresh方法实现的。整个启动过程包含三个部分。BeanDefinition的Resource定位、加载和注冊三个基本部分。Spring将三个模块分开。并使用不同的模块完毕。

    第一个过程是Resource定位过程。这个Resource定位是指Spring找到我们定义的Bean配置的xml文件。

    第二步。BeanDefinition的加载。这个过程是把用户定义好的Bean表示成IoC容器内部的数据结构,而这个数据结构就是BeanDefinition。详细说。BeanDefination实际就是POJO在容器中的抽象,通过这个BeanDefinition定义的数据结构,使IoC容器可以方便的对POJO对象。也就是Bean进行管理。

    第三步,是向IoC容器注冊这些BeanDefinition的过程。这个过程通过调用BeanDefinationRegistry接口实现。

这个注冊过程把加载过程(第二步)得到的BeanDefinition向容器注冊。IoC内部,将BeanDefinition注入到一个HashMap中去,IoC容器就是通过HashMap来持有这些BeanDefinition数据的。

    一般,IoC的初始化过程,不包含依赖注入。依赖注入一般发生在应用第一次通过getBean向容器获取Bean的时候。

1,BeanDefinition的Resource定位。

  在使用DefaultListableBeanFactory的时候,首先须要使用Resource来进行资源定位容器使用的BeanDefinition。

    使用ClassPathResource进行资源定位。

    1. ClassPathResource re = new ClassPathResource("bean.xml");

    在此处定义的资源文件不能被DefaultListableBeanFactory直接使用,通过BeanDefinitionReader来读取。

    1. DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

    2. XmlBeanDefinitionReader xdr = new XmlBeanDefinitionReader(beanFactory);

    3. xdr.loadBeanDefinitions(re);

在此处我们发现使用比較麻烦。所以使用ApplicationContext,由于在ApplicationContext中。Spring为我们提供了一系列的资源定位,比方FileSystemXmlApplicationContext。


    以FileSystemXmlApplicationContext为例,解说相应的源代码。

    该构造函数通过文件路劲来生成相应的FileSystemXmlApplicationContext

    1. public FileSystemXmlApplicationContext(String configLocation) throws BeansException {

    2. this(new String[] {configLocation}, true, null);

    3. }

通过refresh方法来加载BeanDefinition。



    1. public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)

    2. throws BeansException {

    1. super(parent);

    2. setConfigLocations(configLocations);

    3. if (refresh) {

    4. refresh();

    5. }

    6. }

通过文件系统来获取资源。


    1. @Override

    2. protected Resource getResourceByPath(String path) {

    3. if (path != null && path.startsWith("/")) {

    4. path = path.substring(1);

    5. }

    6. return new FileSystemResource(path);

    7. }

2,BeanDefinition的加载和解析。

    对IoC容器来说。加载过程相当于把BeanDefinition在IoC容器中转换成一个Spring内部数据结构的过程。IoC对对象的管理都是通过对其持有的BeanDefination进行相关操作来实现的。

这些BeanDefinition是通过HashMap来维护的。

    1. public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)

    2. throws BeansException {

    3. super(parent);

    4. setConfigLocations(configLocations);

    5. if (refresh) {

    6. refresh();

    7. }

    8. }


    如上代码,refresh()方法启动了容器初始化。是加载BeanDefination的入口方法。
    refresh()详细的代码结构例如以下:

    1. @Override

    2. public void refresh() throws BeansException, IllegalStateException {

    3. synchronized (this.startupShutdownMonitor) {

    4. // Prepare this context for refreshing.

    5. prepareRefresh();

    1. // Tell the subclass to refresh the internal bean factory.

    1. //在子类中启动refreshBeanFactory()的地方。

    2. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

    1. // Prepare the bean factory for use in this context.

    2. prepareBeanFactory(beanFactory);

    1. try {

    2. // Allows post-processing of the bean factory in context subclasses.

    1. //设置BeanFactory的后置处理。

    1. postProcessBeanFactory(beanFactory);

    1. // Invoke factory processors registered as beans in the context.

    1. //调用BeanFactory的后置处理器。这些处理器是在Bean定义中向容器注冊的

    1. invokeBeanFactoryPostProcessors(beanFactory);

    1. // Register bean processors that intercept bean creation.

    1. //注冊Bean的后处理器。在Bean的创建过程中调用

    1. registerBeanPostProcessors(beanFactory);

    1. // Initialize message source for this context.

    1. //对上下文中的消息源初始化

    1. initMessageSource();

    1. // Initialize event multicaster for this context.

    1. //初始化上下文中的时间机制

    2. initApplicationEventMulticaster();

    1. // Initialize other special beans in specific context subclasses.

    1. //初始化其它Bean

    1. onRefresh();

    1. // Check for listener beans and register them.

    1. //检查监听bean并注冊

    1. registerListeners();

    1. // Instantiate all remaining (non-lazy-init) singletons.

    1. //实例化全部(non-lazy-init) 单例。

    2. finishBeanFactoryInitialization(beanFactory);

    1. // Last step: publish corresponding event.

    1. //公布容器事件。结束

    1. finishRefresh();

    2. }

    1. catch (BeansException ex) {

    2. // Destroy already created singletons to avoid dangling resources.

    1. //防止Bean资源占用,销毁已经创建的单例。

    2. destroyBeans();

    1. // Reset ‘active‘ flag.

    1. //重置active标志

    1. cancelRefresh(ex);

    1. // Propagate exception to caller.

    2. throw ex;

    3. }

    4. }

    5. }


-1。prepareRefresh():

    1. /**
    2. * Prepare this context for refreshing, setting its startup date and
    3. * active flag as well as performing any initialization of property sources.
    4. */
    5. protected void prepareRefresh() {
    6. this.startupDate = System.currentTimeMillis();
    1. synchronized (this.activeMonitor) {
    2. this.active = true;
    3. }
    1. if (logger.isInfoEnabled()) {
    2. logger.info("Refreshing " + this);
    3. }
    1. // Initialize any placeholder property sources in the context environment
    2. initPropertySources();
    1. // Validate that all properties marked as required are resolvable
    2. // see ConfigurablePropertyResolver#setRequiredProperties
    3. getEnvironment().validateRequiredProperties();
    4. }

-2。启动refreshBeanFactory():

    1. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

    1. /**
    2. * Tell the subclass to refresh the internal bean factory.
    3. * @return the fresh BeanFactory instance
    4. * @see #refreshBeanFactory()
    5. * @see #getBeanFactory()
    6. */
    7. protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    8. refreshBeanFactory();
    9. ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    10. if (logger.isDebugEnabled()) {
    11. logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    12. }
    13. return beanFactory;
    14. }

终于调用,AbstractRefreshableApplicationContext中的refreshBeanFactory()方法。


    1. /**
    2. * This implementation performs an actual refresh of this context‘s underlying
    3. * bean factory, shutting down the previous bean factory (if any) and
    4. * initializing a fresh bean factory for the next phase of the context‘s lifecycle.
    5. */
    6. @Override
    7. protected final void refreshBeanFactory() throws BeansException {
    8. if (hasBeanFactory()) {//假设已经存在BeanFactory
    9. destroyBeans();//销毁
    10. closeBeanFactory();
    11. }
    12. try { //创建IoC容器
    13. DefaultListableBeanFactory beanFactory = createBeanFactory();
    14. beanFactory.setSerializationId(getId());
    15. customizeBeanFactory(beanFactory);
    16. loadBeanDefinitions(beanFactory);//加载BeanFactory。抽象方法
    17. synchronized (this.beanFactoryMonitor) {
    18. this.beanFactory = beanFactory;
    19. }
    20. }
    21. catch (IOException ex) {
    22. throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    23. }
    24. }

这里调用的loadBeanDefinations()是一个抽象方法,详细实如今AbstractXmlApplicationContext。

    1. /**
    2. * Loads the bean definitions via an XmlBeanDefinitionReader.
    3. * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
    4. * @see #initBeanDefinitionReader
    5. * @see #loadBeanDefinitions
    6. */
    7. @Override
    8. protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    9. // Create a new XmlBeanDefinitionReader for the given BeanFactory.
    10. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    1. // Configure the bean definition reader with this context‘s
    2. // resource loading environment.
    3. beanDefinitionReader.setEnvironment(this.getEnvironment());
    4. beanDefinitionReader.setResourceLoader(this);
    5. beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    1. // Allow a subclass to provide custom initialization of the reader,
    2. // then proceed with actually loading the bean definitions.
    3. initBeanDefinitionReader(beanDefinitionReader);
    4. loadBeanDefinitions(beanDefinitionReader);
    5. }

接着就是调用loadBeanDefinations的地方,首先得到BeanDefinition信息的Resource定位,然后调用XmlBeanDefinitionReader来读取,详细过程托付给BeanDefinitionReader来完毕的。

XML文件则是通过XmlBeanDefinitionReader来加载BeanDefination到容器中。

    ?注:在XmlBeanDefinationReader中找到的loadBeanDefination()方法。与书中的代码块不同。

此处可能是Spring版本号的问题。

    1. public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    2. Assert.notNull(encodedResource, "EncodedResource must not be null");
    3. if (logger.isInfoEnabled()) {
    4. logger.info("Loading XML bean definitions from " + encodedResource.getResource());
    5. }
    1. Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    2. if (currentResources == null) {
    3. currentResources = new HashSet<EncodedResource>(4);
    4. this.resourcesCurrentlyBeingLoaded.set(currentResources);
    5. }
    6. if (!currentResources.add(encodedResource)) {
    7. throw new BeanDefinitionStoreException(
    8. "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    9. }
    10. try {//输入流读取资源
    11. InputStream inputStream = encodedResource.getResource().getInputStream();
    12. try {
    13. InputSource inputSource = new InputSource(inputStream);
    14. if (encodedResource.getEncoding() != null) {
    15. inputSource.setEncoding(encodedResource.getEncoding());
    16. }//调用解析XML文件
    17. return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    18. }
    19. finally {
    20. inputStream.close();
    21. }
    22. }
    23. catch (IOException ex) {
    24. throw new BeanDefinitionStoreException(
    25. "IOException parsing XML document from " + encodedResource.getResource(), ex);
    26. }
    27. finally {
    28. currentResources.remove(encodedResource);
    29. if (currentResources.isEmpty()) {
    30. this.resourcesCurrentlyBeingLoaded.remove();
    31. }
    32. }
    33. }

doLoadBeanDefinitions()方法:

    1. protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
    2. throws BeanDefinitionStoreException {
    3. try {
    4. //载入文件
    5. Document doc = doLoadDocument(inputSource, resource);
    6. //启动具体的解析过程
    7. return registerBeanDefinitions(doc, resource);
    8. }
    9. catch (BeanDefinitionStoreException ex) {
    10. throw ex;
    11. }
    12. catch (SAXParseException ex) {
    13. throw new XmlBeanDefinitionStoreException(resource.getDescription(),
    14. "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
    15. }
    16. catch (SAXException ex) {
    17. throw new XmlBeanDefinitionStoreException(resource.getDescription(),
    18. "XML document from " + resource + " is invalid", ex);
    19. }
    20. catch (ParserConfigurationException ex) {
    21. throw new BeanDefinitionStoreException(resource.getDescription(),
    22. "Parser configuration exception parsing XML from " + resource, ex);
    23. }
    24. catch (IOException ex) {
    25. throw new BeanDefinitionStoreException(resource.getDescription(),
    26. "IOException parsing XML document from " + resource, ex);
    27. }
    28. catch (Throwable ex) {
    29. throw new BeanDefinitionStoreException(resource.getDescription(),
    30. "Unexpected exception parsing XML document from " + resource, ex);
    31. }
    32. }

registerbeanDefinitions()方法代码:

    1. public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    2. //获取XML文档读取
    3. BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    4. documentReader.setEnvironment(this.getEnvironment());
    5. int countBefore = getRegistry().getBeanDefinitionCount();
    6. //详细解析过程
    7. documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    8. return getRegistry().getBeanDefinitionCount() - countBefore;
    9. }

BeanDefinition加载过程中,首先调用XML解析器,生成XML解析对象。然后再进行详细的解析。

createBeanDefinitionDocumentReader()方法:

    1. protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
    2. return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
    3. }

获取到详细的解析器。然后托付给BeanDefinitionParserDelegate来完毕详细的解析。例如以下查看DefaultBeanDefinitionDocuementReader中的processBeanDefinition(Element , BeanDefinitionParserDelegate)方法:

    1. protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    2. BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

    1. //BeanDefinitionHolder是对BeanDefinition的封装。

    1. if (bdHolder != null) {
    2. bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
    3. try {
    4. // Register the final decorated instance.

    1. //向IoC容器注冊解析到的BeanDefinition。

    2. BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
    3. }
    4. catch (BeanDefinitionStoreException ex) {
    5. getReaderContext().error("Failed to register bean definition with name ‘" +
    6. bdHolder.getBeanName() + "‘", ele, ex);
    7. }
    8. // Send registration event.
    9. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    10. }
    11. }

BeanDefinitionHolder:

    1. public class BeanDefinitionHolder implements BeanMetadataElement {
    1. private final BeanDefinition beanDefinition;
    1. private final String beanName;
    1. private final String[] aliases;
    1. ........

BeanDefinitionParserDelegate类中,定义了对各种SpringBean类的处理。

查看其相应的parseBeanDefinitionElement方法:

    1. public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
    2. String id = ele.getAttribute(ID_ATTRIBUTE);//bean元素中的ID
    3. String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);//bean元素中的name
    1. List<String> aliases = new ArrayList<String>();//aliases
    2. if (StringUtils.hasLength(nameAttr)) {
    3. String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
    4. aliases.addAll(Arrays.asList(nameArr));
    5. }
    1. String beanName = id;
    2. if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
    3. beanName = aliases.remove(0);
    4. if (logger.isDebugEnabled()) {
    5. logger.debug("No XML ‘id‘ specified - using ‘" + beanName +
    6. "‘ as bean name and " + aliases + " as aliases");
    7. }
    8. }
    1. if (containingBean == null) {
    2. checkNameUniqueness(beanName, aliases, ele);
    3. }
    1. AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);//具体解析过程,返回AbstractBeanDefinition对象,该对象定义了Bean的基本属性
    2. if (beanDefinition != null) {
    3. if (!StringUtils.hasText(beanName)) {
    4. try {
    5. if (containingBean != null) {
    6. beanName = BeanDefinitionReaderUtils.generateBeanName(
    7. beanDefinition, this.readerContext.getRegistry(), true);
    8. }
    9. else {
    10. beanName = this.readerContext.generateBeanName(beanDefinition);
    11. // Register an alias for the plain bean class name, if still possible,
    12. // if the generator returned the class name plus a suffix.
    13. // This is expected for Spring 1.2/2.0 backwards compatibility.
    14. String beanClassName = beanDefinition.getBeanClassName();
    15. if (beanClassName != null &&
    16. beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
    17. !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
    18. aliases.add(beanClassName);
    19. }
    20. }
    21. if (logger.isDebugEnabled()) {
    22. logger.debug("Neither XML ‘id‘ nor ‘name‘ specified - " +
    23. "using generated bean name [" + beanName + "]");
    24. }
    25. }
    26. catch (Exception ex) {
    27. error(ex.getMessage(), ele);
    28. return null;
    29. }
    30. }
    31. String[] aliasesArray = StringUtils.toStringArray(aliases);
    32. return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    33. }
    1. return null;
    2. }

查看详细的解析代码,parseBeanDefinitionEleent方法:

    1. public AbstractBeanDefinition parseBeanDefinitionElement(
    2. Element ele, String beanName, BeanDefinition containingBean) {
    1. this.parseState.push(new BeanEntry(beanName));
    1. String className = null;
    2. if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
    3. className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    4. }
    1. try {
    2. String parent = null;
    3. if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
    4. parent = ele.getAttribute(PARENT_ATTRIBUTE);
    5. }
    6. //生成BeanDefinition对象
    7. AbstractBeanDefinition bd = createBeanDefinition(className, parent);
    8. //解析属性,并设置Description信息
    9. parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
    10. bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
    11. //解析bean元素信息
    12. parseMetaElements(ele, bd);
    13. parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
    14. parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
    15. //构造函数
    16. parseConstructorArgElements(ele, bd);
    17. //成员变量
    18. parsePropertyElements(ele, bd);
    19. parseQualifierElements(ele, bd);
    20. bd.setResource(this.readerContext.getResource());
    21. bd.setSource(extractSource(ele));
    1. return bd;
    2. }
    3. catch (ClassNotFoundException ex) {
    4. error("Bean class [" + className + "] not found", ele, ex);
    5. }
    6. catch (NoClassDefFoundError err) {
    7. error("Class that bean class [" + className + "] depends on not found", ele, err);
    8. }
    9. catch (Throwable ex) {
    10. error("Unexpected failure during bean definition parsing", ele, ex);
    11. }
    12. finally {
    13. this.parseState.pop();
    14. }
    1. return null;
    2. }

当中相应的各种异常信息,可能我们在编程工作中常常遇到。

    1. public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
    2. NodeList nl = beanEle.getChildNodes();
    3. for (int i = 0; i < nl.getLength(); i++) {
    4. Node node = nl.item(i);
    5. if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
    6. parsePropertyElement((Element) node, bd);//解析
    7. }
    8. }
    9. }

    1. /**
    2. * Parse a property element.
    3. */
    4. public void parsePropertyElement(Element ele, BeanDefinition bd) {
    5. String propertyName = ele.getAttribute(NAME_ATTRIBUTE);//获取property名字
    6. if (!StringUtils.hasLength(propertyName)) {
    7. error("Tag ‘property‘ must have a ‘name‘ attribute", ele);
    8. return;
    9. }
    10. this.parseState.push(new PropertyEntry(propertyName));
    11. try {
    12. if (bd.getPropertyValues().contains(propertyName)) {//是否包括
    13. error("Multiple ‘property‘ definitions for property ‘" + propertyName + "‘", ele);
    14. return;
    15. }
    16. Object val = parsePropertyValue(ele, bd, propertyName);//解析
    17. PropertyValue pv = new PropertyValue(propertyName, val);//获取值
    18. parseMetaElements(ele, pv);
    19. pv.setSource(extractSource(ele));
    20. bd.getPropertyValues().addPropertyValue(pv);
    21. }
    22. finally {
    23. this.parseState.pop();
    24. }
    25. }
    1. public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
    2. String elementName = (propertyName != null) ?
    3. "<property> element for property ‘" + propertyName + "‘" :
    4. "<constructor-arg> element";
    1. // Should only have one child element: ref, value, list, etc.
    2. NodeList nl = ele.getChildNodes();//xml文档解析
    3. Element subElement = null;
    4. for (int i = 0; i < nl.getLength(); i++) {
    5. Node node = nl.item(i);
    6. if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
    7. !nodeNameEquals(node, META_ELEMENT)) {
    8. // Child element is what we‘re looking for.
    9. if (subElement != null) {
    10. error(elementName + " must not contain more than one sub-element", ele);
    11. }
    12. else {
    13. subElement = (Element) node;
    14. }
    15. }
    16. }
    1. boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);//是否是ref引用
    2. boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);//值引用
    3. if ((hasRefAttribute && hasValueAttribute) ||
    4. ((hasRefAttribute || hasValueAttribute) && subElement != null)) {
    5. error(elementName +
    6. " is only allowed to contain either ‘ref‘ attribute OR ‘value‘ attribute OR sub-element", ele);
    7. }
    1. if (hasRefAttribute) {//ref引用
    2. String refName = ele.getAttribute(REF_ATTRIBUTE);
    3. if (!StringUtils.hasText(refName)) {
    4. error(elementName + " contains empty ‘ref‘ attribute", ele);
    5. }
    6. RuntimeBeanReference ref = new RuntimeBeanReference(refName);
    7. ref.setSource(extractSource(ele));
    8. return ref;
    9. }//value 引用
    10. else if (hasValueAttribute) {
    11. TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
    12. valueHolder.setSource(extractSource(ele));
    13. return valueHolder;
    14. }//假设还有子元素。触发对子元素的解析
    15. else if (subElement != null) {
    16. return parsePropertySubElement(subElement, bd);
    17. }
    18. else {
    19. // Neither child element nor "ref" or "value" attribute found.
    20. error(elementName + " must specify a ref or value", ele);
    21. return null;
    22. }
    23. }

3,BeanDefinition在IoC容器中的注冊

BeanDefinition完毕加载和解析过程后。须要对其进行注冊操作。

注冊是在DefaultListableBeanFactory中,通过HashMap来加载Beandefinition的。

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

调用顺序:XmlBeanDefinitionReader调用loadBeanDefinitions(EncodedResource)方法,然后到registerBeanDefinitions()方法。在该方法中registerBeanDefinitions()方法被调用。在DefaultListableBeanFactory中,实现了BeanDefinitionRegistry接口。

    1. @Override
    2. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
    3. throws BeanDefinitionStoreException {
    1. Assert.hasText(beanName, "Bean name must not be empty");
    2. Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    1. if (beanDefinition instanceof AbstractBeanDefinition) {
    2. try {
    3. ((AbstractBeanDefinition) beanDefinition).validate();
    4. }
    5. catch (BeanDefinitionValidationException ex) {
    6. throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
    7. "Validation of bean definition failed", ex);
    8. }
    9. }
    1. synchronized (this.beanDefinitionMap) {//是否存在同样名字
    2. BeanDefinition oldBeanDefinition = this.beanDefinitionMap.get(beanName);
    3. if (oldBeanDefinition != null) {
    4. if (!this.allowBeanDefinitionOverriding) {
    5. throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
    6. "Cannot register bean definition [" + beanDefinition + "] for bean ‘" + beanName +
    7. "‘: There is already [" + oldBeanDefinition + "] bound.");
    8. }
    9. else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
    10. // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
    11. if (this.logger.isWarnEnabled()) {
    12. this.logger.warn("Overriding user-defined bean definition for bean ‘" + beanName +
    13. " with a framework-generated bean definition ‘: replacing [" +
    14. oldBeanDefinition + "] with [" + beanDefinition + "]");
    15. }
    16. }
    17. else {
    18. if (this.logger.isInfoEnabled()) {
    19. this.logger.info("Overriding bean definition for bean ‘" + beanName +
    20. "‘: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
    21. }
    22. }
    23. }
    24. else {//注冊bean。将bean的name放入List
    25. this.beanDefinitionNames.add(beanName);
    26. this.frozenBeanDefinitionNames = null;
    27. }

    1. //map中增加

    2. this.beanDefinitionMap.put(beanName, beanDefinition);
    3. }
    1. resetBeanDefinition(beanName);
    2. }
完毕了注冊。就完毕了IoC容器的初始化。

在使用的IoC容器的DefaultListableBeanFactory中已经建立了Bean的配置信息,并且这些BeanDefinition已经能够被容器使用,他们都在beanDefinitionMap中被检索和使用。容器的作用就是对这些信息进行维护和处理。

IoC容器的依赖注入    ?    ?

    ?依赖注入是用户第一次向Ioc容器索要Bean的时候触发的。除非通过lazy-init控制Bean的记载时机。

    ?从DefaultListableBeanFactory的基类AbstractBeanFactory的getBean方法開始查看实现。

    1. @Override
    2. public Object getBean(String name) throws BeansException {
    3. return doGetBean(name, null, null, false);
    4. }
    1. @Override
    2. public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
    3. return doGetBean(name, requiredType, null, false);
    4. }
    1. @Override
    2. public Object getBean(String name, Object... args) throws BeansException {
    3. return doGetBean(name, null, args, false);
    4. }

查看doGetBean方法:

    1. protected <T> T doGetBean(
    2. final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
    3. throws BeansException {
    1. final String beanName = transformedBeanName(name);
    2. Object bean;
    1. // Eagerly check singleton cache for manually registered singletons.
    2. //从缓存入手。处理单例bean
    3. Object sharedInstance = getSingleton(beanName);
    4. if (sharedInstance != null && args == null) {
    5. if (logger.isDebugEnabled()) {
    6. if (isSingletonCurrentlyInCreation(beanName)) {
    7. logger.debug("Returning eagerly cached instance of singleton bean ‘" + beanName +
    8. "‘ that is not fully initialized yet - a consequence of a circular reference");
    9. }
    10. else {
    11. logger.debug("Returning cached instance of singleton bean ‘" + beanName + "‘");
    12. }
    13. }
    14. //对FactoryBean的处理,获取FactoryBean的相关实例。
    15. bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    16. }
    1. else {
    2. // Fail if we‘re already creating this bean instance:
    3. // We‘re assumably within a circular reference.
    4. if (isPrototypeCurrentlyInCreation(beanName)) {
    5. throw new BeanCurrentlyInCreationException(beanName);
    6. }
    1. // Check if bean definition exists in this factory.
    2. //减产是否已经存在相应的BeanDefinition对象
    3. BeanFactory parentBeanFactory = getParentBeanFactory();
    4. if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    5. // Not found -> check parent.
    6. String nameToLookup = originalBeanName(name);
    7. if (args != null) {
    8. // Delegation to parent with explicit args.
    9. return (T) parentBeanFactory.getBean(nameToLookup, args);
    10. }
    11. else {
    12. // No args -> delegate to standard getBean method.
    13. return parentBeanFactory.getBean(nameToLookup, requiredType);
    14. }
    15. }
    1. if (!typeCheckOnly) {
    2. markBeanAsCreated(beanName);
    3. }
    1. try {
    2. //依据Bean的名字获取BeanDefinition
    3. final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    4. checkMergedBeanDefinition(mbd, beanName, args);
    1. // Guarantee initialization of beans that the current bean depends on.
    2. //获取当前bean的全部依赖bean
    3. String[] dependsOn = mbd.getDependsOn();
    4. if (dependsOn != null) {
    5. for (String dependsOnBean : dependsOn) {
    6. if (isDependent(beanName, dependsOnBean)) {
    7. throw new BeanCreationException("Circular depends-on relationship between ‘" +
    8. beanName + "‘ and ‘" + dependsOnBean + "‘");
    9. }
    10. registerDependentBean(dependsOnBean, beanName);//注冊依赖bean
    11. getBean(dependsOnBean);//获取bean的递归调用
    12. }
    13. }
    1. // Create bean instance.
    2. //创建单例bean
    3. if (mbd.isSingleton()) {
    4. sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
    5. @Override
    6. public Object getObject() throws BeansException {
    7. try {
    8. return createBean(beanName, mbd, args);
    9. }
    10. catch (BeansException ex) {
    11. // Explicitly remove instance from singleton cache: It might have been put there
    12. // eagerly by the creation process, to allow for circular reference resolution.
    13. // Also remove any beans that received a temporary reference to the bean.
    14. destroySingleton(beanName);
    15. throw ex;
    16. }
    17. }
    18. });
    19. bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    20. }
    1. else if (mbd.isPrototype()) {// property bean
    2. // It‘s a prototype -> create a new instance.
    3. Object prototypeInstance = null;
    4. try {
    5. beforePrototypeCreation(beanName);
    6. prototypeInstance = createBean(beanName, mbd, args);
    7. }
    8. finally {
    9. afterPrototypeCreation(beanName);
    10. }
    11. bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    12. }
    1. else {
    2. String scopeName = mbd.getScope();//其它scope
    3. final Scope scope = this.scopes.get(scopeName);
    4. if (scope == null) {
    5. throw new IllegalStateException("No Scope registered for scope ‘" + scopeName + "‘");
    6. }
    7. try {
    8. Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
    9. @Override
    10. public Object getObject() throws BeansException {
    11. beforePrototypeCreation(beanName);
    12. try {
    13. return createBean(beanName, mbd, args);
    14. }
    15. finally {
    16. afterPrototypeCreation(beanName);
    17. }
    18. }
    19. });
    20. bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    21. }
    22. catch (IllegalStateException ex) {
    23. throw new BeanCreationException(beanName,
    24. "Scope ‘" + scopeName + "‘ is not active for the current thread; " +
    25. "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
    26. ex);
    27. }
    28. }
    29. }
    30. catch (BeansException ex) {
    31. cleanupAfterBeanCreationFailure(beanName);
    32. throw ex;
    33. }
    34. }
    1. // Check if required type matches the type of the actual bean instance.
    2. //检查bean的类型。
    3. if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
    4. try {
    5. return getTypeConverter().convertIfNecessary(bean, requiredType);
    6. }
    7. catch (TypeMismatchException ex) {
    8. if (logger.isDebugEnabled()) {
    9. logger.debug("Failed to convert bean ‘" + name + "‘ to required type [" +
    10. ClassUtils.getQualifiedName(requiredType) + "]", ex);
    11. }
    12. throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    13. }
    14. }
    15. return (T) bean;
    16. }

这种方法就是依赖注入的入口,由于他触发了依赖注入。

虽然能够以最简单的方法来描写叙述Spring IoC容器,即Spring容器就是一个HashMap,通过HashMap来管理BeanDefinition对象。

在getBean()的时候,会触发createBean()来进创建须要的Bean对象。

    ?终于的调用,到AbstractAutowireCapableBeanFactory的createBean()方法,代码例如以下:

    1. /**
    2. * Central method of this class: creates a bean instance,
    3. * populates the bean instance, applies post-processors, etc.
    4. * @see #doCreateBean
    5. */
    6. @Override
    7. protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
    8. throws BeanCreationException {
    1. if (logger.isDebugEnabled()) {
    2. logger.debug("Creating instance of bean ‘" + beanName + "‘");
    3. }
    4. // Make sure bean class is actually resolved at this point.

    1. //推断须要创建的Bean是否可实例化,这个类是否可通过类装载器来加载

    2. resolveBeanClass(mbd, beanName);
    1. // Prepare method overrides.
    2. try {
    3. mbd.prepareMethodOverrides();
    4. }
    5. catch (BeanDefinitionValidationException ex) {
    6. throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
    7. beanName, "Validation of method overrides failed", ex);
    8. }
    1. try {
    2. // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.

    1. //假设Bean配置了BeanPostProcessors,则返回代理对象

    2. Object bean = resolveBeforeInstantiation(beanName, mbd);
    3. if (bean != null) {
    4. return bean;
    5. }
    6. }
    7. catch (Throwable ex) {
    8. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    9. "BeanPostProcessor before instantiation of bean failed", ex);
    10. }

    1. //创建bean

    1. Object beanInstance = doCreateBean(beanName, mbd, args);
    2. if (logger.isDebugEnabled()) {
    3. logger.debug("Finished creating instance of bean ‘" + beanName + "‘");
    4. }
    5. return beanInstance;
    6. }

再查看doCreateBean()方法:

    1. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
    2. // Instantiate the bean.
    3. BeanWrapper instanceWrapper = null;
    4. if (mbd.isSingleton()) {//假设是单例的。则移除缓存中的同name bean

    5. instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    6. }
    7. if (instanceWrapper == null) {//创建Bean
    8. instanceWrapper = createBeanInstance(beanName, mbd, args);
    9. }
    10. final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    11. Class<?

      > beanType = (instanceWrapper != null ?

      instanceWrapper.getWrappedClass() : null);

    1. // Allow post-processors to modify the merged bean definition.
    2. synchronized (mbd.postProcessingLock) {
    3. if (!mbd.postProcessed) {
    4. applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    5. mbd.postProcessed = true;
    6. }
    7. }
    1. // Eagerly cache singletons to be able to resolve circular references
    2. // even when triggered by lifecycle interfaces like BeanFactoryAware.
    3. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    4. isSingletonCurrentlyInCreation(beanName));
    5. if (earlySingletonExposure) {
    6. if (logger.isDebugEnabled()) {
    7. logger.debug("Eagerly caching bean ‘" + beanName +
    8. "‘ to allow for resolving potential circular references");
    9. }
    10. addSingletonFactory(beanName, new ObjectFactory<Object>() {
    11. @Override
    12. public Object getObject() throws BeansException {
    13. return getEarlyBeanReference(beanName, mbd, bean);
    14. }
    15. });
    16. }
    1. // Initialize the bean instance.初始化bean。通常在此处发生依赖注入
    2. Object exposedObject = bean;
    3. try {
    4. populateBean(beanName, mbd, instanceWrapper);
    5. if (exposedObject != null) {
    6. exposedObject = initializeBean(beanName, exposedObject, mbd);
    7. }
    8. }
    9. catch (Throwable ex) {
    10. if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
    11. throw (BeanCreationException) ex;
    12. }
    13. else {
    14. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
    15. }
    16. }
    1. if (earlySingletonExposure) {
    2. Object earlySingletonReference = getSingleton(beanName, false);
    3. if (earlySingletonReference != null) {
    4. if (exposedObject == bean) {
    5. exposedObject = earlySingletonReference;
    6. }
    7. else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
    8. String[] dependentBeans = getDependentBeans(beanName);
    9. Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
    10. for (String dependentBean : dependentBeans) {
    11. if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
    12. actualDependentBeans.add(dependentBean);
    13. }
    14. }
    15. if (!actualDependentBeans.isEmpty()) {
    16. throw new BeanCurrentlyInCreationException(beanName,
    17. "Bean with name ‘" + beanName + "‘ has been injected into other beans [" +
    18. StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
    19. "] in its raw version as part of a circular reference, but has eventually been " +
    20. "wrapped. This means that said other beans do not use the final version of the " +
    21. "bean. This is often the result of over-eager type matching - consider using " +
    22. "‘getBeanNamesOfType‘ with the ‘allowEagerInit‘ flag turned off, for example.");
    23. }
    24. }
    25. }
    26. }
    1. // Register bean as disposable.
    2. try {
    3. registerDisposableBeanIfNecessary(beanName, bean, mbd);
    4. }
    5. catch (BeanDefinitionValidationException ex) {
    6. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    7. }
    1. return exposedObject;
    2. }

与依赖注入相关的两个方法:createBeanInstance和populateBean。

 

    1. protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
    2. // Make sure bean class is actually resolved at this point.

    1. //确认须要创建实例的类能够实例化

    2. Class<?> beanClass = resolveBeanClass(mbd, beanName);
    1. if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
    2. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    3. "Bean class isn‘t public, and non-public access not allowed: " + beanClass.getName());
    4. }

    1. //工厂方法实例化

    2. if (mbd.getFactoryMethodName() != null) {
    3. return instantiateUsingFactoryMethod(beanName, mbd, args);
    4. }
    1. // Shortcut when re-creating the same bean...
    2. boolean resolved = false;
    3. boolean autowireNecessary = false;
    4. if (args == null) {
    5. synchronized (mbd.constructorArgumentLock) {
    6. if (mbd.resolvedConstructorOrFactoryMethod != null) {
    7. resolved = true;
    8. autowireNecessary = mbd.constructorArgumentsResolved;
    9. }
    10. }
    11. }
    12. if (resolved) {
    13. if (autowireNecessary) {
    14. return autowireConstructor(beanName, mbd, null, null);
    15. }
    16. else {
    17. return instantiateBean(beanName, mbd);
    18. }
    19. }
    1. //构造函数实例化
    2. Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    3. if (ctors != null ||
    4. mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
    5. mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
    6. return autowireConstructor(beanName, mbd, ctors, args);
    7. }
    1. // 使用无參构造函数
    2. return instantiateBean(beanName, mbd);
    3. }
    1. protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {

    1. //使用CGLIB对bean进行实例化。

    1. try {
    2. Object beanInstance;
    3. final BeanFactory parent = this;
    4. if (System.getSecurityManager() != null) {
    5. beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
    6. @Override
    7. public Object run() {
    8. return getInstantiationStrategy().instantiate(mbd, beanName, parent);
    9. }
    10. }, getAccessControlContext());
    11. }
    12. else {
    13. beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
    14. }
    15. BeanWrapper bw = new BeanWrapperImpl(beanInstance);
    16. initBeanWrapper(bw);
    17. return bw;
    18. }
    19. catch (Throwable ex) {
    20. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    21. }
    22. }

在Bean实例化后,就是相关的依赖关系。

    ?依赖注入的发生是在BeanWrapper的setPropertyValues中实现。详细实现是在BeanWrapper的子类,BeanWrapperImpl中实现。


以上便是整个IoC过程创建Bean的总体思路。与书中相比,省略了部分代码。

ApplicationContext和Bean的初始化及销毁

    ?ApplicationContext的启动是在AbstractApplicationContext中实现。

    ?相同的销毁操作是在doClose()方法中完毕。

    1. protected void doClose() {
    2. boolean actuallyClose;
    3. synchronized (this.activeMonitor) {
    4. actuallyClose = this.active && !this.closed;
    5. this.closed = true;
    6. }
    1. if (actuallyClose) {
    2. if (logger.isInfoEnabled()) {
    3. logger.info("Closing " + this);
    4. }
    1. LiveBeansView.unregisterApplicationContext(this);
    1. try {
    2. // Publish shutdown event.
    3. publishEvent(new ContextClosedEvent(this));
    4. }
    5. catch (Throwable ex) {
    6. logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
    7. }
    1. // Stop all Lifecycle beans, to avoid delays during individual destruction.
    2. try {
    3. getLifecycleProcessor().onClose();
    4. }
    5. catch (Throwable ex) {
    6. logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
    7. }
    1. // Destroy all cached singletons in the context‘s BeanFactory.
    2. destroyBeans();
    1. // Close the state of this context itself.
    2. closeBeanFactory();
    1. // Let subclasses do some final clean-up if they wish...
    2. onClose();
    1. synchronized (this.activeMonitor) {
    2. this.active = false;
    3. }
    4. }
    5. }

    ?Bean的销毁和创建,Spring通过IoC管理Bean的生命周期来实现。

Spring中Bean的生命周期包括:

    ?    ?-1。Bean实例的创建。


    ?    ?-2,为Bean实例设置属性。


    ?    ?-3。调用Bean的初始化方法。

    ?    ?-4,通过IoC获取Bean。


    ?    ?-5,当容器关闭的时候调用bean的销毁方法。

总结

    ?BeanDefinition的定位。对IoC容器来说,它为管理POJO直接的关系提供了帮助,但也要依据Spring的定义规则提供Bean定义信息。在Bean定义方面,Spring为用户提供了非常大的灵活性。在初始化过程中,首先须要定义到这些有效地Bean定义信息。这里Spring使用Resource接口来统一这些信息。而定位由ResourceLoader完毕。

    ?容器的初始化。容器的初始化过程是在refresh()方法中完毕的。这个refresh()相当于容器的初始化函数。在初始化中,比較重要的就是对Bean信息的加载和注冊功能。

?

《Spring技术内幕》笔记-第二章 IoC容器的实现

标签:事务   clean   npos   pretty   stream   pre   into   ifreq   runtime   

原文地址:http://www.cnblogs.com/llguanli/p/6940239.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!