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

简介

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信息的载入和注册功能。

?

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-01 16:47:36

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

spring技术内幕笔记1

spring的设计目标(为什么要用spring) 如果我们要简要地描述Spring的设计目标,可以这么说,Spring为开发者提供的是一个一站式的轻量级应用开发框架(平台).作为平台,Spring抽象了我们在许多应用开发中遇到的共性问题:同时,作为一个轻量级的应用开发框架,Spring和传统的J2EE开发相比,有其自身的特点.通过这些自身的特点, Spring充分体现了它的设计理念:在Java EE的应用开发中,支持POJO和使用JavaBean的开发方式,使应用面向接口开发,充分支持OO(面向

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

前一段时候我把Spring技术内幕的关于IOC原理一章看完,感觉代码太多,不好掌握,我特意又各方搜集了一些关于IOC原理的资料,特加深一下印象,以便真正掌握IOC的原理. IOC的思想是:Spring容器来实现这些相互依赖对象的创建.协调工作.对象只需要关系业务逻辑本身就可以了. SpringIOC容器的执行步骤是: 1.资源定位,即首先要找到applicationContext.xml文件 2.BeanDefinition的载入,把XML文件中的数据统一加载到BeanDefinition中,方

读《Spring-技术内幕》-第二章:IoC容器的实现-2

IoC容器系列的设计与实现 概要 博客介绍了BeanFactory这个容器的基本接口,如getBean(String name),containsBean(String name)等等,但是这些接口并没有具体的实现,因此给出了XmlBeanFactory容器的实现过程,还用编程的方式使用了DefaultListableBeanFactory这个容器,成功得获得了在BeanDefinition中定义的一个Bean.通过编程式的使用,让我们明白IoC容器中的关键的类之间的相互依赖关系,如Resour

Spring技术内幕——Spring Framework的IOC容器实现(一)

一.SpringIOC容器概述 IOC容器和依赖反转的模式 在面向对象的系统中,对象封装了数据和对数据的处理,对象的依赖关系常常体现在对数据和方法的依赖上.这些依赖关系可以通过把对象的依赖注入交给框架IOC容器来完成.他可以再解耦代码的同时提高了代码的可测试性. 依赖控制反转的实现由很多种方式,在Spring中,IOC容器是实现这个模式的载体,他可以再对象生成或者初始化时直接将数据注入到对象中,也可以通过将对象引用注入到对象数据域中的方式来注入对方法调用的依赖.这种依赖注入是可以递归的,对象被逐

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

第2章.IoC容器 IoC容器概述 abstract: 介绍IoC和bean的用处和使用 IoC容器处于整个Spring框架中比较核心的位置:Core Container: Beans, Core, Context, SpEL 为上层AOP/Aspects/Instrumentation/Messaging提供支持 IoC容器的用途: 创建对象的依赖,最后组装成所需的业务对象 容器通过业务对象和配置(application-context.xml; xxxController.java)-->生

《spring技术内幕》读书笔记——什么是POJO模式

今天在看<spring技术内幕>,第一章中多次提到了使用POJO来完成开发,就百度了一下,在此保留 1.     什么是POJO POJO的名称有多种,pure old java object .plain ordinary java object 等. 按照Martin Fowler的解释是“Plain Old Java Object”,从字面上翻译为“纯洁老式的java对象”,但大家都使用“简单java对象”来称呼它. POJO的内在含义是指那些没有从任何类继承.也没有实现任何接口,更没有

Spring技术内幕:设计理念和整体架构概述

程序员都很崇拜技术大神,很大一部分是因为他们发现和解决问题的能力,特别是线上出现紧急问题时,总是能够快速定位和解决. 一方面,他们有深厚的技术基础,对应用的技术知其所以然,另一方面,在采坑的过程中不断总结,积累了很多经验. 相信大家都使用过Spring,有些人了解它的核心:IOC和AOP,但只是了解它们的基本概念.使用了反射和动态代理,关于如何管理对象.代理的具体实现了解的比较浅. 有些人使用Spring MVC,使用Spring集成数据库.事务.消息队列以简化操作,但对集成的具体设计思路和实现

深入探索spring技术内幕(一): spring概述

一.Spring是什么? Spring是一个开源的控制反转 ( IoC ) 和面向切面 ( AOP ) 的容器框架, 它的主要目的是简化企业开发. 二.控制反转(IoC) 控制反转: 所谓的控制反转就是应用本身不负责依赖对象的创建及维护, 依赖对象的创建及维护是由外部容器负责的. 这样控制权就由应用转移到了外部容器, 控制权的转移就是所谓的反转. public class PersonServiceBean { // 自己new一个对象 private PersonDao personDao =

SQL Server技术内幕笔记合集

SQL Server技术内幕笔记合集 发这一篇文章主要是方便大家找到我的笔记入口,方便大家o(∩_∩)o Microsoft SQL Server 6.5 技术内幕 笔记http://www.cnblogs.com/lyhabc/articles/3914213.html Microsoft SQL Server 2005技术内幕:T-SQL查询笔记http://www.cnblogs.com/lyhabc/articles/3912608.html Microsoft SQL Server 2