码迷,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 {

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

  5. /**

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

  7. */

  8. public XmlBeanFactory(Resource resource) throws BeansException {

  9. this(resource, null);

  10. }

  11. /**

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

  13. * which must be parsable using DOM.

  14. */

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

  16. super(parentBeanFactory);

  17. this.reader.loadBeanDefinitions(resource);

  18. }

  19. }

    该类继承了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 {

  3. super(parent);

  4. setConfigLocations(configLocations);

  5. if (refresh) {

  6. refresh();

  7. }

  8. }


    在实例化该应用中,调用了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 {

  3. super(parent);

  4. setConfigLocations(configLocations);

  5. if (refresh) {

  6. refresh();

  7. }

  8. }

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


  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();

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

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

  8. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

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

  10. prepareBeanFactory(beanFactory);

  11. try {

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

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

  14. postProcessBeanFactory(beanFactory);

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

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

  17. invokeBeanFactoryPostProcessors(beanFactory);

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

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

  20. registerBeanPostProcessors(beanFactory);

  21. // Initialize message source for this context.

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

  23. initMessageSource();

  24. // Initialize event multicaster for this context.

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

  26. initApplicationEventMulticaster();

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

  28. //初始化其它Bean

  29. onRefresh();

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

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

  32. registerListeners();

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

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

  35. finishBeanFactoryInitialization(beanFactory);

  36. // Last step: publish corresponding event.

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

  38. finishRefresh();

  39. }

  40. catch (BeansException ex) {

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

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

  43. destroyBeans();

  44. // Reset ‘active‘ flag.

  45. //重置active标志

  46. cancelRefresh(ex);

  47. // Propagate exception to caller.

  48. throw ex;

  49. }

  50. }

  51. }


-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();
  7. synchronized (this.activeMonitor) {
  8. this.active = true;
  9. }
  10. if (logger.isInfoEnabled()) {
  11. logger.info("Refreshing " + this);
  12. }
  13. // Initialize any placeholder property sources in the context environment
  14. initPropertySources();
  15. // Validate that all properties marked as required are resolvable
  16. // see ConfigurablePropertyResolver#setRequiredProperties
  17. getEnvironment().validateRequiredProperties();
  18. }

-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);
  11. // Configure the bean definition reader with this context‘s
  12. // resource loading environment.
  13. beanDefinitionReader.setEnvironment(this.getEnvironment());
  14. beanDefinitionReader.setResourceLoader(this);
  15. beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
  16. // Allow a subclass to provide custom initialization of the reader,
  17. // then proceed with actually loading the bean definitions.
  18. initBeanDefinitionReader(beanDefinitionReader);
  19. loadBeanDefinitions(beanDefinitionReader);
  20. }

接着就是调用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. }
  6. Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
  7. if (currentResources == null) {
  8. currentResources = new HashSet<EncodedResource>(4);
  9. this.resourcesCurrentlyBeingLoaded.set(currentResources);
  10. }
  11. if (!currentResources.add(encodedResource)) {
  12. throw new BeanDefinitionStoreException(
  13. "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
  14. }
  15. try {//输入流读取资源
  16. InputStream inputStream = encodedResource.getResource().getInputStream();
  17. try {
  18. InputSource inputSource = new InputSource(inputStream);
  19. if (encodedResource.getEncoding() != null) {
  20. inputSource.setEncoding(encodedResource.getEncoding());
  21. }//调用解析XML文件
  22. return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
  23. }
  24. finally {
  25. inputStream.close();
  26. }
  27. }
  28. catch (IOException ex) {
  29. throw new BeanDefinitionStoreException(
  30. "IOException parsing XML document from " + encodedResource.getResource(), ex);
  31. }
  32. finally {
  33. currentResources.remove(encodedResource);
  34. if (currentResources.isEmpty()) {
  35. this.resourcesCurrentlyBeingLoaded.remove();
  36. }
  37. }
  38. }

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);

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

  4. if (bdHolder != null) {
  5. bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
  6. try {
  7. // Register the final decorated instance.

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

  9. BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
  10. }
  11. catch (BeanDefinitionStoreException ex) {
  12. getReaderContext().error("Failed to register bean definition with name ‘" +
  13. bdHolder.getBeanName() + "‘", ele, ex);
  14. }
  15. // Send registration event.
  16. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
  17. }
  18. }

BeanDefinitionHolder:

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

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

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

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

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

  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";
  5. // Should only have one child element: ref, value, list, etc.
  6. NodeList nl = ele.getChildNodes();//xml文档解析
  7. Element subElement = null;
  8. for (int i = 0; i < nl.getLength(); i++) {
  9. Node node = nl.item(i);
  10. if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
  11. !nodeNameEquals(node, META_ELEMENT)) {
  12. // Child element is what we‘re looking for.
  13. if (subElement != null) {
  14. error(elementName + " must not contain more than one sub-element", ele);
  15. }
  16. else {
  17. subElement = (Element) node;
  18. }
  19. }
  20. }
  21. boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);//是否是ref引用
  22. boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);//值引用
  23. if ((hasRefAttribute && hasValueAttribute) ||
  24. ((hasRefAttribute || hasValueAttribute) && subElement != null)) {
  25. error(elementName +
  26. " is only allowed to contain either ‘ref‘ attribute OR ‘value‘ attribute OR sub-element", ele);
  27. }
  28. if (hasRefAttribute) {//ref引用
  29. String refName = ele.getAttribute(REF_ATTRIBUTE);
  30. if (!StringUtils.hasText(refName)) {
  31. error(elementName + " contains empty ‘ref‘ attribute", ele);
  32. }
  33. RuntimeBeanReference ref = new RuntimeBeanReference(refName);
  34. ref.setSource(extractSource(ele));
  35. return ref;
  36. }//value 引用
  37. else if (hasValueAttribute) {
  38. TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
  39. valueHolder.setSource(extractSource(ele));
  40. return valueHolder;
  41. }//假设还有子元素。触发对子元素的解析
  42. else if (subElement != null) {
  43. return parsePropertySubElement(subElement, bd);
  44. }
  45. else {
  46. // Neither child element nor "ref" or "value" attribute found.
  47. error(elementName + " must specify a ref or value", ele);
  48. return null;
  49. }
  50. }

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

  42. //map中增加

  43. this.beanDefinitionMap.put(beanName, beanDefinition);
  44. }
  45. resetBeanDefinition(beanName);
  46. }
完毕了注冊。就完毕了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. }
  5. @Override
  6. public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
  7. return doGetBean(name, requiredType, null, false);
  8. }
  9. @Override
  10. public Object getBean(String name, Object... args) throws BeansException {
  11. return doGetBean(name, null, args, false);
  12. }

查看doGetBean方法:

  1. protected <T> T doGetBean(
  2. final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
  3. throws BeansException {
  4. final String beanName = transformedBeanName(name);
  5. Object bean;
  6. // Eagerly check singleton cache for manually registered singletons.
  7. //从缓存入手。处理单例bean
  8. Object sharedInstance = getSingleton(beanName);
  9. if (sharedInstance != null && args == null) {
  10. if (logger.isDebugEnabled()) {
  11. if (isSingletonCurrentlyInCreation(beanName)) {
  12. logger.debug("Returning eagerly cached instance of singleton bean ‘" + beanName +
  13. "‘ that is not fully initialized yet - a consequence of a circular reference");
  14. }
  15. else {
  16. logger.debug("Returning cached instance of singleton bean ‘" + beanName + "‘");
  17. }
  18. }
  19. //对FactoryBean的处理,获取FactoryBean的相关实例。
  20. bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  21. }
  22. else {
  23. // Fail if we‘re already creating this bean instance:
  24. // We‘re assumably within a circular reference.
  25. if (isPrototypeCurrentlyInCreation(beanName)) {
  26. throw new BeanCurrentlyInCreationException(beanName);
  27. }
  28. // Check if bean definition exists in this factory.
  29. //减产是否已经存在相应的BeanDefinition对象
  30. BeanFactory parentBeanFactory = getParentBeanFactory();
  31. if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
  32. // Not found -> check parent.
  33. String nameToLookup = originalBeanName(name);
  34. if (args != null) {
  35. // Delegation to parent with explicit args.
  36. return (T) parentBeanFactory.getBean(nameToLookup, args);
  37. }
  38. else {
  39. // No args -> delegate to standard getBean method.
  40. return parentBeanFactory.getBean(nameToLookup, requiredType);
  41. }
  42. }
  43. if (!typeCheckOnly) {
  44. markBeanAsCreated(beanName);
  45. }
  46. try {
  47. //依据Bean的名字获取BeanDefinition
  48. final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
  49. checkMergedBeanDefinition(mbd, beanName, args);
  50. // Guarantee initialization of beans that the current bean depends on.
  51. //获取当前bean的全部依赖bean
  52. String[] dependsOn = mbd.getDependsOn();
  53. if (dependsOn != null) {
  54. for (String dependsOnBean : dependsOn) {
  55. if (isDependent(beanName, dependsOnBean)) {
  56. throw new BeanCreationException("Circular depends-on relationship between ‘" +
  57. beanName + "‘ and ‘" + dependsOnBean + "‘");
  58. }
  59. registerDependentBean(dependsOnBean, beanName);//注冊依赖bean
  60. getBean(dependsOnBean);//获取bean的递归调用
  61. }
  62. }
  63. // Create bean instance.
  64. //创建单例bean
  65. if (mbd.isSingleton()) {
  66. sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
  67. @Override
  68. public Object getObject() throws BeansException {
  69. try {
  70. return createBean(beanName, mbd, args);
  71. }
  72. catch (BeansException ex) {
  73. // Explicitly remove instance from singleton cache: It might have been put there
  74. // eagerly by the creation process, to allow for circular reference resolution.
  75. // Also remove any beans that received a temporary reference to the bean.
  76. destroySingleton(beanName);
  77. throw ex;
  78. }
  79. }
  80. });
  81. bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
  82. }
  83. else if (mbd.isPrototype()) {// property bean
  84. // It‘s a prototype -> create a new instance.
  85. Object prototypeInstance = null;
  86. try {
  87. beforePrototypeCreation(beanName);
  88. prototypeInstance = createBean(beanName, mbd, args);
  89. }
  90. finally {
  91. afterPrototypeCreation(beanName);
  92. }
  93. bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
  94. }
  95. else {
  96. String scopeName = mbd.getScope();//其它scope
  97. final Scope scope = this.scopes.get(scopeName);
  98. if (scope == null) {
  99. throw new IllegalStateException("No Scope registered for scope ‘" + scopeName + "‘");
  100. }
  101. try {
  102. Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
  103. @Override
  104. public Object getObject() throws BeansException {
  105. beforePrototypeCreation(beanName);
  106. try {
  107. return createBean(beanName, mbd, args);
  108. }
  109. finally {
  110. afterPrototypeCreation(beanName);
  111. }
  112. }
  113. });
  114. bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
  115. }
  116. catch (IllegalStateException ex) {
  117. throw new BeanCreationException(beanName,
  118. "Scope ‘" + scopeName + "‘ is not active for the current thread; " +
  119. "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
  120. ex);
  121. }
  122. }
  123. }
  124. catch (BeansException ex) {
  125. cleanupAfterBeanCreationFailure(beanName);
  126. throw ex;
  127. }
  128. }
  129. // Check if required type matches the type of the actual bean instance.
  130. //检查bean的类型。
  131. if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
  132. try {
  133. return getTypeConverter().convertIfNecessary(bean, requiredType);
  134. }
  135. catch (TypeMismatchException ex) {
  136. if (logger.isDebugEnabled()) {
  137. logger.debug("Failed to convert bean ‘" + name + "‘ to required type [" +
  138. ClassUtils.getQualifiedName(requiredType) + "]", ex);
  139. }
  140. throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
  141. }
  142. }
  143. return (T) bean;
  144. }

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

虽然能够以最简单的方法来描写叙述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 {
  9. if (logger.isDebugEnabled()) {
  10. logger.debug("Creating instance of bean ‘" + beanName + "‘");
  11. }
  12. // Make sure bean class is actually resolved at this point.

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

  14. resolveBeanClass(mbd, beanName);
  15. // Prepare method overrides.
  16. try {
  17. mbd.prepareMethodOverrides();
  18. }
  19. catch (BeanDefinitionValidationException ex) {
  20. throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
  21. beanName, "Validation of method overrides failed", ex);
  22. }
  23. try {
  24. // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.

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

  26. Object bean = resolveBeforeInstantiation(beanName, mbd);
  27. if (bean != null) {
  28. return bean;
  29. }
  30. }
  31. catch (Throwable ex) {
  32. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  33. "BeanPostProcessor before instantiation of bean failed", ex);
  34. }

  35. //创建bean

  36. Object beanInstance = doCreateBean(beanName, mbd, args);
  37. if (logger.isDebugEnabled()) {
  38. logger.debug("Finished creating instance of bean ‘" + beanName + "‘");
  39. }
  40. return beanInstance;
  41. }

再查看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);

  12. // Allow post-processors to modify the merged bean definition.
  13. synchronized (mbd.postProcessingLock) {
  14. if (!mbd.postProcessed) {
  15. applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
  16. mbd.postProcessed = true;
  17. }
  18. }
  19. // Eagerly cache singletons to be able to resolve circular references
  20. // even when triggered by lifecycle interfaces like BeanFactoryAware.
  21. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
  22. isSingletonCurrentlyInCreation(beanName));
  23. if (earlySingletonExposure) {
  24. if (logger.isDebugEnabled()) {
  25. logger.debug("Eagerly caching bean ‘" + beanName +
  26. "‘ to allow for resolving potential circular references");
  27. }
  28. addSingletonFactory(beanName, new ObjectFactory<Object>() {
  29. @Override
  30. public Object getObject() throws BeansException {
  31. return getEarlyBeanReference(beanName, mbd, bean);
  32. }
  33. });
  34. }
  35. // Initialize the bean instance.初始化bean。通常在此处发生依赖注入
  36. Object exposedObject = bean;
  37. try {
  38. populateBean(beanName, mbd, instanceWrapper);
  39. if (exposedObject != null) {
  40. exposedObject = initializeBean(beanName, exposedObject, mbd);
  41. }
  42. }
  43. catch (Throwable ex) {
  44. if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
  45. throw (BeanCreationException) ex;
  46. }
  47. else {
  48. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
  49. }
  50. }
  51. if (earlySingletonExposure) {
  52. Object earlySingletonReference = getSingleton(beanName, false);
  53. if (earlySingletonReference != null) {
  54. if (exposedObject == bean) {
  55. exposedObject = earlySingletonReference;
  56. }
  57. else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
  58. String[] dependentBeans = getDependentBeans(beanName);
  59. Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
  60. for (String dependentBean : dependentBeans) {
  61. if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
  62. actualDependentBeans.add(dependentBean);
  63. }
  64. }
  65. if (!actualDependentBeans.isEmpty()) {
  66. throw new BeanCurrentlyInCreationException(beanName,
  67. "Bean with name ‘" + beanName + "‘ has been injected into other beans [" +
  68. StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
  69. "] in its raw version as part of a circular reference, but has eventually been " +
  70. "wrapped. This means that said other beans do not use the final version of the " +
  71. "bean. This is often the result of over-eager type matching - consider using " +
  72. "‘getBeanNamesOfType‘ with the ‘allowEagerInit‘ flag turned off, for example.");
  73. }
  74. }
  75. }
  76. }
  77. // Register bean as disposable.
  78. try {
  79. registerDisposableBeanIfNecessary(beanName, bean, mbd);
  80. }
  81. catch (BeanDefinitionValidationException ex) {
  82. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
  83. }
  84. return exposedObject;
  85. }

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

 

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

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

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

  9. //工厂方法实例化

  10. if (mbd.getFactoryMethodName() != null) {
  11. return instantiateUsingFactoryMethod(beanName, mbd, args);
  12. }
  13. // Shortcut when re-creating the same bean...
  14. boolean resolved = false;
  15. boolean autowireNecessary = false;
  16. if (args == null) {
  17. synchronized (mbd.constructorArgumentLock) {
  18. if (mbd.resolvedConstructorOrFactoryMethod != null) {
  19. resolved = true;
  20. autowireNecessary = mbd.constructorArgumentsResolved;
  21. }
  22. }
  23. }
  24. if (resolved) {
  25. if (autowireNecessary) {
  26. return autowireConstructor(beanName, mbd, null, null);
  27. }
  28. else {
  29. return instantiateBean(beanName, mbd);
  30. }
  31. }
  32. //构造函数实例化
  33. Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
  34. if (ctors != null ||
  35. mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
  36. mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
  37. return autowireConstructor(beanName, mbd, ctors, args);
  38. }
  39. // 使用无參构造函数
  40. return instantiateBean(beanName, mbd);
  41. }
  1. protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {

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

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

在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. }
  7. if (actuallyClose) {
  8. if (logger.isInfoEnabled()) {
  9. logger.info("Closing " + this);
  10. }
  11. LiveBeansView.unregisterApplicationContext(this);
  12. try {
  13. // Publish shutdown event.
  14. publishEvent(new ContextClosedEvent(this));
  15. }
  16. catch (Throwable ex) {
  17. logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
  18. }
  19. // Stop all Lifecycle beans, to avoid delays during individual destruction.
  20. try {
  21. getLifecycleProcessor().onClose();
  22. }
  23. catch (Throwable ex) {
  24. logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
  25. }
  26. // Destroy all cached singletons in the context‘s BeanFactory.
  27. destroyBeans();
  28. // Close the state of this context itself.
  29. closeBeanFactory();
  30. // Let subclasses do some final clean-up if they wish...
  31. onClose();
  32. synchronized (this.activeMonitor) {
  33. this.active = false;
  34. }
  35. }
  36. }

    ?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
迷上了代码!