简单介绍

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

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

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

-2。ApplicationContext应用上下文。

Spring IoC容器的设计

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

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

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的继承结构图。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

下面是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容器的实现的更多相关文章

  1. Mysql技术内幕-笔记-第二章 数据类型

    第二章 数据类型 Mysql中尽量不要使用UNSIGNED,因为可能会带来一些意想不到的效果 SHOW CREATE TABLE tablename\G;查看表的创建语句 ZEROFILL会将宽度小于 ...

  2. Spring技术内幕笔记2--我懒不写了哈哈哈哈。

    目录 1.1 关于IOC容器设计的线路区别 1.1.1 BeanFactory 1.1.2 ApplicationContext 2.1 FileSystemXmlApplicationContext ...

  3. Spring技术内幕:SpringIOC原理学习总结

    前一段时候我把Spring技术内幕的关于IOC原理一章看完,感觉代码太多,不好掌握,我特意又各方搜集了一些关于IOC原理的资料,特加深一下印象,以便真正掌握IOC的原理. IOC的思想是:Spring ...

  4. Java开发工程师(Web方向) - 04.Spring框架 - 第2章.IoC容器

    第2章.IoC容器 IoC容器概述 abstract: 介绍IoC和bean的用处和使用 IoC容器处于整个Spring框架中比较核心的位置:Core Container: Beans, Core, ...

  5. 《spring技术内幕》读书笔记(1)——什么是POJO模式

    今天在看<spring技术内幕>,第一章中多次提到了使用POJO来完成开发,就百度了一下,在此保留 1.     什么是POJO POJO的名称有多种,pure old java obje ...

  6. Spring技术内幕:设计理念和整体架构概述(转)

    程序员都很崇拜技术大神,很大一部分是因为他们发现和解决问题的能力,特别是线上出现紧急问题时,总是能够快速定位和解决. 一方面,他们有深厚的技术基础,对应用的技术知其所以然,另一方面,在采坑的过程中不断 ...

  7. Servlet工作原理解析 《深入分析java web 技术内幕》第九章

    参考关于servblet的相关文章 侧重概况:https://blog.csdn.net/levycc/article/details/50728921 ibm的相关:https://www.ibm. ...

  8. SQL Server技术内幕笔记合集

    SQL Server技术内幕笔记合集 发这一篇文章主要是方便大家找到我的笔记入口,方便大家o(∩_∩)o Microsoft SQL Server 6.5 技术内幕 笔记http://www.cnbl ...

  9. Android群英传笔记——第二章:Android开发工具新接触

    Android群英传笔记--第二章:Android开发工具新接触 其实这一章并没什么可讲的,前面的安装Android studio的我们可以直接跳过,如果有兴趣的,可以去看看Google主推-Andr ...

随机推荐

  1. asp.net mvc 最简单身份验证 [Authorize]通过的标准

    [Authorize] public ContentResult Index2() { return Content("验证通过了"); } 经常能够看到某个Controler下的 ...

  2. fcc html5 css 练习3

    行内样式看起来是这样的 <h1 style="color: green"> .pink-text { color: pink !important; }         ...

  3. android学习之路资料集合

    版权声明:本文为 stormzhang 原创文章,可以随意转载,但必须在明确位置注明出处!!! 这篇博客背后的故事 一路走来很不容易,刚好知乎上被人邀请回答如何自学android编程, 就借这个机会在 ...

  4. 支付宝小程序日期选择组件datePicker封装

    github 地址 https://github.com/iocool/antminDatePicker 最近在做支付宝小程序(以下简称小程序)开发,发现小程序的日期选择组件很不好用,比如安卓和IOS ...

  5. Windows2008 Server 常规设置及基本安全策略

    一.系统及程序 1.屏幕保护与电源 桌面右键--〉个性化--〉屏幕保护程序屏幕保护程序 选择无更改电源设置 选择高性能选择关闭显示器的时间 关闭显示器 选 从不 保存修改 2.安装IIS 管理工具-- ...

  6. 【技术累积】【点】【java】【21】序列化二三事

    基础概念 把对象等转为二进制进行传输的是序列化,反之为反序列化: 应用场景一般为读写文件,传输数据/接口调用: Externalizable和Serializable java的序列化方式有两种: S ...

  7. CPU内部组成及原理

    CPU,Central Processing Unit,翻译过来叫中央处理器.是一块超大规模的集成电路,是一台计算机的运算核心(Core)和控制核心( Control Unit).电脑中所有操作都由C ...

  8. Array.prototype.slice.call()的理解

    最近在看廖雪峰的JS课程,浏览器中的操作DOM的那一章,有这样一道题. JavaScript Swift HTML ANSI C CSS DirectX <!-- HTML结构 --> & ...

  9. [nodejs]在mac环境下如何将node更新至最新?

    在mac下安装angular-cli时,报出较多错误.初步怀疑是因为node环境版本过低导致. 在mac下,需要执行如下几步将node更新至最新版本,也可以更新到指定版本 1. sudo npm ca ...

  10. Tomcat启动失败--Several ports (8005, 8080, 8009)

    启动Tomcat服务器报错: Several ports (8005, 8080, 8009) required by Tomcat v7.0 Server at localhost are alre ...