如何查看源码

Spring源码下载https://github.com/spring-projects/spring-framework/tags?after=v3.1.0.RC1

eclipse关联源码 自己百度吧

源代码结构组织

Build-spring-framework是整个Spring源代码的构建目录,里面是项目的构建脚本,如果要自己动手构建Spring,可以进入这个目录使用ANT进行构建。

l  org.springframework.context是IoC容器的源代码目录

l  org.springframework.aop是AOP实现的源代码目录

l  org.springframework.jdbc是JDBC的源代码部分

l  org.springframework.orm是O/R Mapping对应的源代码实现部分

SpringIOC源码分析

IOC初始化

1、 XmlBeanFactory(屌丝IOC)的整个流程

2、 FileSystemXmlApplicationContext 的IOC容器流程

1、高富帅IOC解剖

2、 设置资源加载器和资源定位

3、AbstractApplicationContext的refresh函数载入Bean定义过程:

4、AbstractApplicationContext子类的refreshBeanFactory()方法:

5、AbstractRefreshableApplicationContext子类的loadBeanDefinitions方法:

6、AbstractBeanDefinitionReader读取Bean定义资源:

7、资源加载器获取要读入的资源:

8、XmlBeanDefinitionReader加载Bean定义资源:

9、DocumentLoader将Bean定义资源转换为Document对象:

10、XmlBeanDefinitionReader解析载入的Bean定义资源文件:

11、DefaultBeanDefinitionDocumentReader对Bean定义的Document对象解析:

12、BeanDefinitionParserDelegate解析Bean定义资源文件中的<Bean>元素:

13、BeanDefinitionParserDelegate解析<property>元素:

14、解析<property>元素的子元素:

15、解析<list>子元素:

16、解析过后的BeanDefinition在IoC容器中的注册:

17、DefaultListableBeanFactory向IoC容器注册解析后的BeanDefinition:

IOC体系

BeanFactory

Spring Bean的创建是典型的工厂模式,这一系列的Bean工厂,也即IOC容器为开发者管理对象间的依赖关系提供了很多便利和基础服务,在Spring中有许多的IOC容器的实现供用户选择和使用,其相互关系如下:

BeanFactory

BeanFactory定义了 IOC 容器的最基本形式,并提供了 IOC 容器应遵守的的最基本的接口,也就是Spring IOC 所遵守的最底层和最基本的编程规范。在  Spring 代码中, BeanFactory 只是个接口,并不是 IOC容器的具体实现,但是 Spring 容器给出了很多种实现,如 DefaultListableBeanFactory 、 XmlBeanFactory 、ApplicationContext 等,都是附加了某种功能的实现。

大体思路是 反射+DOM4J, 解析配置文件,通过beanId查找bean是否存在

存在的话,获取该节点class地址,使用反射机制初始化。

Spring 使用了很多抽象类

Spring核心jar包:

SpringCore -- Spring 核心jar

SpringContext--上下文IOC具体实现

Spring-Bean --  Spring实例

Spring-jdbc

SpringAOP

BeanFactory接口: ctrl+T

核心方法查看:Bean的工厂

定义接口去进行规范

  1. public interface BeanFactory {
  2. //这里是对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,
  3. //如果需要得到工厂本身,需要转义
  4. //转义符“&”用来获取FactoryBean本身
  5. String FACTORY_BEAN_PREFIX = "&";
  6. //根据bean的名字进行获取bean的实例,这是IOC最大的抽象方法
  7. Object getBean(String name) throws BeansException;
  8. //根据bean的名字和Class类型进行获取Bean的实例,和上面方法不同的是,bean名字和Bean 的class类型不同时候会爆出异常
  9. <T> T getBean(String name, Class<T> requiredType) throws BeansException;
  10. <T> T getBean(Class<T> requiredType) throws BeansException;
  11. Object getBean(String name, Object... args) throws BeansException;
  12. //检测这个IOC容器中是否含有这个Bean
  13. boolean containsBean(String name);
  14. //判断这个Bean是不是单利
  15.  
  16. boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
  17. //判断这个Bean是不是原型
  18. boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
  19. //查询指定的bean的名字和Class类型是不是指定的Class类型
  20. boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException;
  21. //这里对得到bean实例的Class类型
  22. Class<?> getType(String name) throws NoSuchBeanDefinitionException;
  23. //这里得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
  24. String[] getAliases(String name);
  25. }

BeanDefinition

这个接口,可以理解为xml bean元素的数据载体。通过对比xml bean标签的属性列表和BeanDefinition的属性列表一看便知。
我的理解,是解析XML的过程,就是 xml <bean>元素内容 转换为BeanDefinition对象的过程。而且这个接口,支持层级,对应对象的继承。
有一个类BeanDefinitionHolder,BeanDefinitionHolder,根据名称或者别名持有beanDefinition,它承载了name和BeanDefinition的映射信息。
BeanWarpper:
提供对标准javabean的分析和操作方法:单个或者批量获取和设置属性值,获取属性描述符,查询属性的可读性和可写性等。支持属性的嵌套设置,深度没有限制。
AbstractRefreshableApplicationContext的refreshBeanFactory()这个方法

核心类:

核心方法:

 这个接口主要做xml解析的

封装xml解析Spring Bean文件的解析封装 (可以get出来个Bean属性哈哈)

方法:

一:

  1. /**
  2. * Return the current bean class name of this bean definition.
  3. * <p>Note that this does not have to be the actual class name used at runtime, in
  4. * case of a child definition overriding/inheriting the class name from its parent.
  5. * Also, this may just be the class that a factory method is called on, or it may
  6. * even be empty in case of a factory bean reference that a method is called on.
  7. * Hence, do <i>not</i> consider this to be the definitive bean type at runtime but
  8. * rather only use it for parsing purposes at the individual bean definition level.
  9. * @see #getParentName()
  10. * @see #getFactoryBeanName()
  11. * @see #getFactoryMethodName()
  12. */
  13. @Nullable
  14. String getBeanClassName();

获取bean的class文件地址  id = xx  class=“”com.tooc5.car“

二:

  1. /**
  2. * Override the target scope of this bean, specifying a new scope name.
  3. * @see #SCOPE_SINGLETON
  4. * @see #SCOPE_PROTOTYPE
  5. */
  6. void setScope(@Nullable String scope);

xml的配置的范围属性

分析看一个类: 分析要分析父类 一直追踪。核心的都封装在父类

点击进入这个抽象类 AbstractRefreshableApplicationContext

看它的方法:refreshBeanFactory()

  1. protected final void refreshBeanFactory() throws BeansException {
  2. if (hasBeanFactory()) {
  3. destroyBeans();
  4. closeBeanFactory();
  5. }
  6. try {
  7. DefaultListableBeanFactory beanFactory = createBeanFactory();//创建IOC容器(Bean工厂)!!!!!!
  8. beanFactory.setSerializationId(getId());
  9. customizeBeanFactory(beanFactory);
  10. loadBeanDefinitions(beanFactory); //载入loadBeanDefinitions 直接把工厂传入进去了
  11. synchronized (this.beanFactoryMonitor) {
  12. this.beanFactory = beanFactory;
  13. }
  14. }
  15. catch (IOException ex) {
  16. throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
  17. }
  18. }

点进入看:

  1. loadBeanDefinitions(beanFactory);
  2.  
  3. 实现类:
  1. @Override
  2. protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
  3. // Create a new XmlBeanDefinitionReader for the given BeanFactory.
  4. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); //读取容器
  5.  
  6. // Configure the bean definition reader with this context's
  7. // resource loading environment.
  8. beanDefinitionReader.setEnvironment(this.getEnvironment());
  9. beanDefinitionReader.setResourceLoader(this); //获取到当前上下文
  10. beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
  11.  
  12. // Allow a subclass to provide custom initialization of the reader,
  13. // then proceed with actually loading the bean definitions.
  14. initBeanDefinitionReader(beanDefinitionReader);
  15. loadBeanDefinitions(beanDefinitionReader);
  16. }

继续点进去看:

  1. loadBeanDefinitions(beanDefinitionReader); 加载配置文件
  1. protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
  2. Resource[] configResources = getConfigResources();
  3. if (configResources != null) {
  4. reader.loadBeanDefinitions(configResources);
  5. }
  6. String[] configLocations = getConfigLocations(); //数组形式 可以加载多个配置文件
  7. if (configLocations != null) {
  8. reader.loadBeanDefinitions(configLocations);
  9. }
  10. }

持续点击:

  1. reader.loadBeanDefinitions(configLocations);
  1. @Override
  2. public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException { //可以传递多个路径进入
  3. Assert.notNull(locations, "Location array must not be null");
  4. int count = 0;
  5. for (String location : locations) {
  6. count += loadBeanDefinitions(location);
  7. }
  8. return count;
  9. }

持续点击:

  1. loadBeanDefinitions(location);
    循环读取配置文件
  1. @Override
  2. public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
  3. return loadBeanDefinitions(location, null);
  4. }

持续点击:

  1. loadBeanDefinitions(location, null);
  1.  
  1. /**
  2. * Load bean definitions from the specified resource location.
  3. * <p>The location can also be a location pattern, provided that the
  4. * ResourceLoader of this bean definition reader is a ResourcePatternResolver.
  5. * @param location the resource location, to be loaded with the ResourceLoader
  6. * (or ResourcePatternResolver) of this bean definition reader
  7. * @param actualResources a Set to be filled with the actual Resource objects
  8. * that have been resolved during the loading process. May be {@code null}
  9. * to indicate that the caller is not interested in those Resource objects.
  10. * @return the number of bean definitions found
  11. * @throws BeanDefinitionStoreException in case of loading or parsing errors
  12. * @see #getResourceLoader()
  13. * @see #loadBeanDefinitions(org.springframework.core.io.Resource)
  14. * @see #loadBeanDefinitions(org.springframework.core.io.Resource[])
  15. */
  16. public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
  17. ResourceLoader resourceLoader = getResourceLoader(); //获取到当配置路径
  18. if (resourceLoader == null) {
  19. throw new BeanDefinitionStoreException(
  20. "Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
  21. }
  22.  
  23. if (resourceLoader instanceof ResourcePatternResolver) {
  24. // Resource pattern matching available.
  25. try {
  26. Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
  27. int count = loadBeanDefinitions(resources);
  28. if (actualResources != null) {
  29. Collections.addAll(actualResources, resources);
  30. }
  31. if (logger.isTraceEnabled()) {
  32. logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
  33. }
  34. return count;
  35. }
  36. catch (IOException ex) {
  37. throw new BeanDefinitionStoreException(
  38. "Could not resolve bean definition resource pattern [" + location + "]", ex);
  39. }
  40. }
  41. else { //////// 看这里
  42. // Can only load single resources by absolute URL.
  43. Resource resource = resourceLoader.getResource(location); //获取资源文件
  44. int count = loadBeanDefinitions(resource);
  45. if (actualResources != null) {
  46. actualResources.add(resource);
  47. }
  48. if (logger.isTraceEnabled()) {
  49. logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
  50. }
  51. return count;
  52. }
  53. }

拿到resource后继续读取,点击

  1. int count = loadBeanDefinitions(resource);

点击xml的 不是配置 文件的

  1. /**
  2. * Load bean definitions from the specified XML file.
  3. * @param resource the resource descriptor for the XML file
  4. * @return the number of bean definitions found
  5. * @throws BeanDefinitionStoreException in case of loading or parsing errors
  6. */
  7. @Override
  8. public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
  9. return loadBeanDefinitions(new EncodedResource(resource));
  10. }

持续点击:

  1. return loadBeanDefinitions(new EncodedResource(resource));
  1. /**
  2. * Load bean definitions from the specified XML file.
  3. * @param encodedResource the resource descriptor for the XML file,
  4. * allowing to specify an encoding to use for parsing the file
  5. * @return the number of bean definitions found
  6. * @throws BeanDefinitionStoreException in case of loading or parsing errors
  7. */
  8. public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
  9. Assert.notNull(encodedResource, "EncodedResource must not be null");
  10. if (logger.isTraceEnabled()) {
  11. logger.trace("Loading XML bean definitions from " + encodedResource);
  12. }
  13.  
  14. Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
  15. if (currentResources == null) {
  16. currentResources = new HashSet<>(4);
  17. this.resourcesCurrentlyBeingLoaded.set(currentResources);
  18. }
  19. if (!currentResources.add(encodedResource)) {
  20. throw new BeanDefinitionStoreException(
  21. "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
  22. }
  23. try {
  24. InputStream inputStream = encodedResource.getResource().getInputStream(); //拿到input流
  25. try {
  26. InputSource inputSource = new InputSource(inputStream); //读取input流
  27. if (encodedResource.getEncoding() != null) {
  28. inputSource.setEncoding(encodedResource.getEncoding()); //进行转码
  29. }
  30. return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
  31. }
  32. finally {
  33. inputStream.close();
  34. }
  35. }
  36. catch (IOException ex) {
  37. throw new BeanDefinitionStoreException(
  38. "IOException parsing XML document from " + encodedResource.getResource(), ex);
  39. }
  40. finally {
  41. currentResources.remove(encodedResource);
  42. if (currentResources.isEmpty()) {
  43. this.resourcesCurrentlyBeingLoaded.remove();
  44. }
  45. }
  46. }
  1. 拿到文件流之后? 持续点击
    return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
  1. protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
  2. throws BeanDefinitionStoreException {
  3.  
  4. try { //XML的DOM4J解析
  5. Document doc = doLoadDocument(inputSource, resource);
  6. int count = registerBeanDefinitions(doc, resource);
  7. if (logger.isDebugEnabled()) {
  8. logger.debug("Loaded " + count + " bean definitions from " + resource);
  9. }
  10. return count;
  11. }
  12. catch (BeanDefinitionStoreException ex) {
  13. throw ex;
  14. }
  15. catch (SAXParseException ex) {
  16. throw new XmlBeanDefinitionStoreException(resource.getDescription(),
  17. "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
  18. }
  19. catch (SAXException ex) {
  20. throw new XmlBeanDefinitionStoreException(resource.getDescription(),
  21. "XML document from " + resource + " is invalid", ex);
  22. }
  23. catch (ParserConfigurationException ex) {
  24. throw new BeanDefinitionStoreException(resource.getDescription(),
  25. "Parser configuration exception parsing XML from " + resource, ex);
  26. }
  27. catch (IOException ex) {
  28. throw new BeanDefinitionStoreException(resource.getDescription(),
  29. "IOException parsing XML document from " + resource, ex);
  30. }
  31. catch (Throwable ex) {
  32. throw new BeanDefinitionStoreException(resource.getDescription(),
  33. "Unexpected exception parsing XML document from " + resource, ex);
  34. }
  35. }
  1. 如何解析的?持续点击:
  1. /**
  2. * Actually load bean definitions from the specified XML file.
  3. * @param inputSource the SAX InputSource to read from
  4. * @param resource the resource descriptor for the XML file
  5. * @return the number of bean definitions found
  6. * @throws BeanDefinitionStoreException in case of loading or parsing errors
  7. * @see #doLoadDocument
  8. * @see #registerBeanDefinitions
  9. */
  10. protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
  11. throws BeanDefinitionStoreException {
  12.  
  13. try {
  14. Document doc = doLoadDocument(inputSource, resource); //解析出doc
  15. int count = registerBeanDefinitions(doc, resource); //注册bean
  16. if (logger.isDebugEnabled()) {
  17. logger.debug("Loaded " + count + " bean definitions from " + resource);
  18. }
  19. return count;
  20. }
  21. catch (BeanDefinitionStoreException ex) {
  22. throw ex;
  23. }
  24. catch (SAXParseException ex) {
  25. throw new XmlBeanDefinitionStoreException(resource.getDescription(),
  26. "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
  27. }
  28. catch (SAXException ex) {
  29. throw new XmlBeanDefinitionStoreException(resource.getDescription(),
  30. "XML document from " + resource + " is invalid", ex);
  31. }
  32. catch (ParserConfigurationException ex) {
  33. throw new BeanDefinitionStoreException(resource.getDescription(),
  34. "Parser configuration exception parsing XML from " + resource, ex);
  35. }
  36. catch (IOException ex) {
  37. throw new BeanDefinitionStoreException(resource.getDescription(),
  38. "IOException parsing XML document from " + resource, ex);
  39. }
  40. catch (Throwable ex) {
  41. throw new BeanDefinitionStoreException(resource.getDescription(),
  42. "Unexpected exception parsing XML document from " + resource, ex);
  43. }
  44. }

拿到:doc 和 resource后,注册bean:持续点击

  1. int count = registerBeanDefinitions(doc, resource);
  1.  
  1. public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
  2. BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
  3. int countBefore = getRegistry().getBeanDefinitionCount();
  4. documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); // 作bean的注册
  5. return getRegistry().getBeanDefinitionCount() - countBefore;
  6. }
  1. 持续点击:
  1. documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
  1. @Override
  2. public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
  3. this.readerContext = readerContext;
  4. doRegisterBeanDefinitions(doc.getDocumentElement());
  5. }

继续点击进入: 从根目录获取到配置文件document。拿到根路径后正式做解析。

  1. /**
  2. * Register each bean definition within the given root {@code <beans/>} element.
  3. */
  4. @SuppressWarnings("deprecation") // for Environment.acceptsProfiles(String...)
  5. protected void doRegisterBeanDefinitions(Element root) {
  6. // Any nested <beans> elements will cause recursion in this method. In
  7. // order to propagate and preserve <beans> default-* attributes correctly,
  8. // keep track of the current (parent) delegate, which may be null. Create
  9. // the new (child) delegate with a reference to the parent for fallback purposes,
  10. // then ultimately reset this.delegate back to its original (parent) reference.
  11. // this behavior emulates a stack of delegates without actually necessitating one.
  12. BeanDefinitionParserDelegate parent = this.delegate;
  13. this.delegate = createDelegate(getReaderContext(), root, parent);
  14.  
  15. if (this.delegate.isDefaultNamespace(root)) {
  16. String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
  17. if (StringUtils.hasText(profileSpec)) {
  18. String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
  19. profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
  20. // We cannot use Profiles.of(...) since profile expressions are not supported
  21. // in XML config. See SPR-12458 for details.
  22. if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
  23. if (logger.isDebugEnabled()) {
  24. logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
  25. "] not matching: " + getReaderContext().getResource());
  26. }
  27. return;
  28. }
  29. }
  30. }
  31.  
  32. preProcessXml(root);
  33. parseBeanDefinitions(root, this.delegate); //做documet解析
  34. postProcessXml(root);
  35.  
  36. this.delegate = parent;
  37. }
  1. 持续点击:
  1. parseBeanDefinitions(root, this.delegate); //做documet解析 从根路径开始解析 遍历节点
  1. /**
  2. * Parse the elements at the root level in the document:
  3. * "import", "alias", "bean".
  4. * @param root the DOM root element of the document
  5. */
  6. protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
  7. if (delegate.isDefaultNamespace(root)) {
  8. NodeList nl = root.getChildNodes();
  9. for (int i = 0; i < nl.getLength(); i++) {
  10. Node node = nl.item(i);
  11. if (node instanceof Element) {
  12. Element ele = (Element) node;
  13. if (delegate.isDefaultNamespace(ele)) {
  14. parseDefaultElement(ele, delegate); //默认解析节点
  15. }
  16. else {
  17. delegate.parseCustomElement(ele); //自定义解析
  18. }
  19. }
  20. }
  21. }
  22. else {
  23. delegate.parseCustomElement(root);
  24. }
  25. }

持续点击进入默认解析:

  1. private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
  2. if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { // input解析
  3. importBeanDefinitionResource(ele);
  4. }
  5. else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { //别名解析
  6. processAliasRegistration(ele);
  7. }
  8. else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { //解析beans
  9. processBeanDefinition(ele, delegate);
  10. }
  11. else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
  12. // recurse
  13. doRegisterBeanDefinitions(ele);
  14. }
  15. }

持续查看解析bean:

  1. processAliasRegistration(ele);
  1. /**
  2. * Process the given bean element, parsing the bean definition
  3. * and registering it with the registry.
  4. */
  5. protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
  6. BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
  7. if (bdHolder != null) {
  8. bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
  9. try {
  10. // Register the final decorated instance.
  11. BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); //可以持续点击查看这里
  12. }
  13. catch (BeanDefinitionStoreException ex) {
  14. getReaderContext().error("Failed to register bean definition with name '" +
  15. bdHolder.getBeanName() + "'", ele, ex);
  16. }
  17. // Send registration event.
  18. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
  19. }
  20. }
  1. 可以持续点击查看这里
  1. BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
  1. /**
  2. * Register the given bean definition with the given bean factory.
  3. * @param definitionHolder the bean definition including name and aliases
  4. * @param registry the bean factory to register with
  5. * @throws BeanDefinitionStoreException if registration failed
  6. */
  7. public static void registerBeanDefinition(
  8. BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
  9. throws BeanDefinitionStoreException {
  10.  
  11. // Register bean definition under primary name.
  12. String beanName = definitionHolder.getBeanName();
  13. registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); //beanName beanId的名称
  14.  
  15. // Register aliases for bean name, if any.
  16. String[] aliases = definitionHolder.getAliases();
  17. if (aliases != null) {
  18. for (String alias : aliases) {
  19. registry.registerAlias(beanName, alias);
  20. }
  21. }
  22. }
  1. beanName beanId的名称 是通过
  1. String beanName = definitionHolder.getBeanName();
  1. 获取的:点击查看 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
  1. @Nullable
  2. public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
  3. String id = ele.getAttribute(ID_ATTRIBUTE); //解析 id
  4. String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); // 解析 name
  5.  
  6. List<String> aliases = new ArrayList<>();
  7. if (StringUtils.hasLength(nameAttr)) {
  8. String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
  9. aliases.addAll(Arrays.asList(nameArr));
  10. }
  11.  
  12. String beanName = id; //通过beanId 找
  13. if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
  14. beanName = aliases.remove(0);
  15. if (logger.isTraceEnabled()) {
  16. logger.trace("No XML 'id' specified - using '" + beanName +
  17. "' as bean name and " + aliases + " as aliases");
  18. }
  19. }
  20.  
  21. if (containingBean == null) {
  22. checkNameUniqueness(beanName, aliases, ele);
  23. }
  24.  
  25. AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
  26. if (beanDefinition != null) {
  27. if (!StringUtils.hasText(beanName)) {
  28. try {
  29. if (containingBean != null) {
  30. beanName = BeanDefinitionReaderUtils.generateBeanName(
  31. beanDefinition, this.readerContext.getRegistry(), true);
  32. }
  33. else {
  34. beanName = this.readerContext.generateBeanName(beanDefinition);
  35. // Register an alias for the plain bean class name, if still possible,
  36. // if the generator returned the class name plus a suffix.
  37. // This is expected for Spring 1.2/2.0 backwards compatibility.
  38. String beanClassName = beanDefinition.getBeanClassName();
  39. if (beanClassName != null &&
  40. beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
  41. !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
  42. aliases.add(beanClassName);
  43. }
  44. }
  45. if (logger.isTraceEnabled()) {
  46. logger.trace("Neither XML 'id' nor 'name' specified - " +
  47. "using generated bean name [" + beanName + "]");
  48. }
  49. }
  50. catch (Exception ex) {
  51. error(ex.getMessage(), ele);
  52. return null;
  53. }
  54. }
  55. String[] aliasesArray = StringUtils.toStringArray(aliases);
  56. return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
  57. }
  58.  
  59. return null;
  60. }
  1. 回退 查看注册的代码,持续点击进入:
    BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
  1. /**
  2. * Register the given bean definition with the given bean factory.
  3. * @param definitionHolder the bean definition including name and aliases
  4. * @param registry the bean factory to register with
  5. * @throws BeanDefinitionStoreException if registration failed
  6. */
  7. public static void registerBeanDefinition(
  8. BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
  9. throws BeanDefinitionStoreException {
  10.  
  11. // Register bean definition under primary name.
  12. String beanName = definitionHolder.getBeanName();
  13. registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); //重点!!!
  14.  
  15. // Register aliases for bean name, if any.
  16. String[] aliases = definitionHolder.getAliases();
  17. if (aliases != null) {
  18. for (String alias : aliases) {
  19. registry.registerAlias(beanName, alias);
  20. }
  21. }
  22. }

重点点击:

好几种注册方式:

选择一种:

  1. @Override
  2. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
  3. throws BeanDefinitionStoreException {
  4.  
  5. Assert.hasText(beanName, "'beanName' must not be empty");
  6. Assert.notNull(beanDefinition, "BeanDefinition must not be null");
  7. this.beanDefinitionMap.put(beanName, beanDefinition);
  8. }

下面插入一段反射代码:

从这里点击进入:

点击:

持续点击进入:

持续点击:

  1. @Nullable
  2. public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
  3. String id = ele.getAttribute(ID_ATTRIBUTE);
  4. String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
  5.  
  6. List<String> aliases = new ArrayList<>();
  7. if (StringUtils.hasLength(nameAttr)) {
  8. String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
  9. aliases.addAll(Arrays.asList(nameArr));
  10. }
  11.  
  12. String beanName = id;
  13. if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
  14. beanName = aliases.remove(0);
  15. if (logger.isTraceEnabled()) {
  16. logger.trace("No XML 'id' specified - using '" + beanName +
  17. "' as bean name and " + aliases + " as aliases");
  18. }
  19. }
  20.  
  21. if (containingBean == null) {
  22. checkNameUniqueness(beanName, aliases, ele);
  23. }
  24.  
  25. AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); //正式开始注册!!!!!!
  26. if (beanDefinition != null) {
  27. if (!StringUtils.hasText(beanName)) {
  28. try {
  29. if (containingBean != null) {
  30. beanName = BeanDefinitionReaderUtils.generateBeanName(
  31. beanDefinition, this.readerContext.getRegistry(), true);
  32. }
  33. else {
  34. beanName = this.readerContext.generateBeanName(beanDefinition);
  35. // Register an alias for the plain bean class name, if still possible,
  36. // if the generator returned the class name plus a suffix.
  37. // This is expected for Spring 1.2/2.0 backwards compatibility.
  38. String beanClassName = beanDefinition.getBeanClassName();
  39. if (beanClassName != null &&
  40. beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
  41. !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
  42. aliases.add(beanClassName);
  43. }
  44. }
  45. if (logger.isTraceEnabled()) {
  46. logger.trace("Neither XML 'id' nor 'name' specified - " +
  47. "using generated bean name [" + beanName + "]");
  48. }
  49. }
  50. catch (Exception ex) {
  51. error(ex.getMessage(), ele);
  52. return null;
  53. }
  54. }
  55. String[] aliasesArray = StringUtils.toStringArray(aliases);
  56. return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
  57. }
  58.  
  59. return null;
  60. }
  1. 持续点击关键代码 注册bean
    核心代码:

持续点击:

持续点击:

  1. public static AbstractBeanDefinition createBeanDefinition(
  2. @Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
  3.  
  4. GenericBeanDefinition bd = new GenericBeanDefinition();
  5. bd.setParentName(parentName);
  6. if (className != null) {
  7. if (classLoader != null) {
  8. bd.setBeanClass(ClassUtils.forName(className, classLoader)); //反射机制初始化bean!
  9. }
  10. else {
  11. bd.setBeanClassName(className);
  12. }
  13. }
  14. return bd;
  15. }
  1. 注意啊 不要点击classPatxXmlApplicationContext 里面没有! 核心 在父类!
  2.  

很多方法写成了一个类 ,一层一个类。看起类是挺不爽的,下伙伴耐心看昂。

可以参考:

https://www.cnblogs.com/ITtangtang/p/3978349.html

Spring IOC 源码解析(持续)的更多相关文章

  1. Spring IoC源码解析之invokeBeanFactoryPostProcessors

    一.Bean工厂的后置处理器 Bean工厂的后置处理器:BeanFactoryPostProcessor(触发时机:bean定义注册之后bean实例化之前)和BeanDefinitionRegistr ...

  2. Spring IoC源码解析之getBean

    一.实例化所有的非懒加载的单实例Bean 从org.springframework.context.support.AbstractApplicationContext#refresh方法开发,进入到 ...

  3. Spring系列(三):Spring IoC源码解析

    一.Spring容器类继承图 二.容器前期准备 IoC源码解析入口: /** * @desc: ioc原理解析 启动 * @author: toby * @date: 2019/7/22 22:20 ...

  4. Spring IoC源码解析——Bean的创建和初始化

    Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...

  5. spring ioc 源码解析

    什么是ioc? 通俗的解释是:(spring)框架中,完成对象的创建和注入的容器. springIOC体系结构: spring IOC的创建是典型的工厂模式,这一系列的bean工厂如上所示. 其核心是 ...

  6. Spring系列(五):Spring AOP源码解析

    一.@EnableAspectJAutoProxy注解 在主配置类中添加@EnableAspectJAutoProxy注解,开启aop支持,那么@EnableAspectJAutoProxy到底做了什 ...

  7. Spring Boot系列(四):Spring Boot源码解析

    一.自动装配原理 之前博文已经讲过,@SpringBootApplication继承了@EnableAutoConfiguration,该注解导入了AutoConfigurationImport Se ...

  8. spring IoC源码分析 (3)Resource解析

    引自 spring IoC源码分析 (3)Resource解析 定义好了Resource之后,看到XmlFactoryBean的构造函数 public XmlBeanFactory(Resource  ...

  9. 深入Spring IOC源码之ResourceLoader

    在<深入Spring IOC源码之Resource>中已经详细介绍了Spring中Resource的抽象,Resource接口有很多实现类,我们当然可以使用各自的构造函数创建符合需求的Re ...

随机推荐

  1. 【Python数据挖掘】决策树、随机森林、Bootsing、

    决策树的定义 决策树(decision tree)是一个树结构(可以是二叉树或非二叉树).其每个非叶节点表示一个特征属性上的测试,每个分支代表这个特征属性在某个值域上的输出,而每个叶节点存放一个类别. ...

  2. MSSQL移除字符串两边的指定字符

    移除字符串左边的字符: CREATE FUNCTION [dbo].[RemoveLeftChar] ( @Expression varchar(max), @char varchar(4))RETU ...

  3. Gartner提出的7种多租户模型

    下面,我们就来看看在SaaS应用搭建过程中,可以采用什么样的多租户模型.从而能较为清晰地了解未来使用PaaS平台开发的SaaS,可以为用户提供哪些多租户的服务.        Gartner提出了7种 ...

  4. Yii2的主从数据库设置

    项目做大了,数据库主从还是不可少的.使用Yii框架开发,如何设置数据库的主从呢?其实很简单. 先说一个主数据库服务器和多个从数据库服务器的情况,修改配置文件 config/db.php ,其中 sla ...

  5. springmvc 之 easyUI开发商城管理系统

    1.分页 url:controller的路径 pageSize:每页显示的行数 ---后台参数名(rows) 会向后台传递一个 page参数,表示当前页.---后台参数名(page) controll ...

  6. 使用selenium实现简单网络爬虫抓取MM图片

    撸主听说有个网站叫他趣,里面有个社区,其中有一项叫他趣girl,撸主点进去看了下,还真不错啊,图文并茂,宅男们自己去看看就知道啦~ 接下来当然就是爬取这些妹子的图片啦,不仅仅是图片,撸主发现里面的对话 ...

  7. Spark Streaming Checkpoint反序列化问题分析

    转载自:https://mp.weixin.qq.com/s/EQgDUSf3TK0oVg1xmg-49Q Checkpoint是Spark Streaming中的核心机制,它为应用程序的7*24小时 ...

  8. win10专业版密钥激活

    win10专业版密钥激活 1.查看激活状态,win按键>设置(左下角倒数第二个)>更新和安全>激活---------提示没有有效密钥,需要激活 2.管理员身份打开cmd,搜索框输入c ...

  9. opencv学习(1.2) - Windows 10 安装OpenCV &配置VS 2015

    windows 10 安装OpenCV&配置VS 2015 环境 系统:Windows 10 OpenCV版本:3.4.1 开发IDE:VS2015 社区版 下载安装 下载OpenCV 3.4 ...

  10. Spring框架第四篇之基于注解的DI注入

    一.说明 与@Component注解功能相同,但意义不同的注解还有三个: 1)@Repository:注解在Dao实现类上 2)@Service:注解在Service实现类上 3)@Controlle ...