• 《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信息的加载和注冊功能。

  • 相关阅读:
    Mybatis 内置 Java 类型别名与 typeHandlers
    泛型方法前为什么要加<T>
    jdbcTemplate学习(四)
    jdbcTemplate学习(三)
    jdbcTemplate学习(二)
    jdbcTemplate学习(一)
    博客园markdown toc
    office,ps 等入门教程链接
    mysql 手动加锁测试
    拆机联想ideapad s500
  • 原文地址:https://www.cnblogs.com/llguanli/p/6940239.html
Copyright © 2020-2023  润新知