框架-spring源码分析(一)

参考:

https://www.cnblogs.com/heavenyes/p/3933642.html

http://www.cnblogs.com/BINGJJFLY/p/9055454.html

https://www.cnblogs.com/leftthen/p/5440107.html

spring容器

一、简介

  spring容器是整个spring框架的核心,通常我们说的spring容器就是bean工厂,bean工厂负责创建和初始化bean、装配bean并且管理应用程序中的bean.spring中提供了两个核心接口:BeanFactory和ApplicationContext,ApplicationContext是BeanFactory子接口,它提供了比BeanFactory更完善的功能.

二、ApplicationContext的工作原理

  先建立一个新的java项目,搭建好spring的开发环境.然后启动spring的容器,如下面的代码:

  1. public class Demo {
  2. public static void main(String[] args) {
        
  3. ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");
  4.  
  5. }
  6. }

 spring容器启动时,会完成两个重要的工作:加载bean的定义信息(BeanDefinition)以及初始化所有单例bean,在初始化bean的过程中注入bean的依赖.bean的定义信息是指:bean的基本属性,例如完整类名,是否单例等等,其实就是<bean id="" class="" scope="">元素的那些属性.在创建bean时需要用到这些属性,所以必须要先加载bean以及它的定义信息.

先说spring容器加载bean的定义信息的实现原理,spring中有两种配置bean的方法:

  • 使用配置文件配置bean,需要在<bean>元素中声明bean的信息;spring容器启动时,会读取配置文件并进行解析,这种情况下,只要解析bean元素就可以获取bean的beanName和它的定义信息.
  • 使用注解配置bean,需要在配置文件中配置bean的路径,例如:<context:component-scan base-package="cn.spring"/>,这样容器启动时就会扫描cn.spring包以及子包下面的所有类,如果类上有@Controller 或者 @Service 或者@Repository或者@Component注解,spring就会加载这些类的定义信息;这里就会有几个问题,第一个问题是如何获取base-package的子包以及包下的所有类?spring的做法是将包名转化成文件系统中的路径,然后traverse获取该目录下的所有.class文件,非常巧妙的一个解决方案!接下来的问题是如何从.class文件中获取bean的定义信息呢?有两种方式,第一种就是把通过.class文件的路径获取该类的包名,然后通过类加载器加载该类获取它的定义信息,第二种方式是用asm框架从class文件中直接读取类的定义信息。spring用的是第二种方式,个人觉得spring选择第二种方式是有以下几个原因,其一,可能需要对class文件进行增强处理,也就是在class文件中增加一些新的指令,在生成代理时可能会需要这样做;其二,反射无法获取类完完全全的信息(例如:方法的参数名称),其三,反射的性能问题;

 接下来,就是容器初始化单例bean的过程:

  spring容器在加载完所有bean的定义信息以后,会有一个refresh()操作,在refresh容器过程中完成两个重要的操作,第一个就是创建所有单例bean,第二个就是装配这些创建bean(注入它们所需要的依赖);

  因为前面的操作已经加载了所有bean的定义信息,并且维护了一个<beanName,BeanDefinition>对应关系的Map,遍历Map,就可以取得每个bean的定义信息,从bean的定义信息可以知道bean是否是单例,如果是单例的,下一步就会根据bean的定义信息来决定bean实例的创建策略,如果配置了bean的factory-method,就调用factory-method创建bean实例,如果没有配置factory-method,默认会调用bean的无参构造函数创建bean实例.

  创建bean实例之后的工作就是装配bean,现在已经拿到了bean实例,如果bean是在配置文件中配置的,此时就会先把配置文件中配置的属性赋值给bean实例上对应的属性;而后由bean的后处理器(BeanPostProcessor)完成bean实例其他属性(通过注解配置的)的注入.如果bean是通过注解进行配置,这时直接就会由bean的后处理器完成bean的装配.完成bean装配的后处理器的工作原理:遍历bean对象的字段和方法,根据字段和方法上应的注解完成相对应的注入操作.

  在装配bean的过程中会出现一个问题:A依赖B,装配A的时候B的实例还没有创建,spring解决这个问题的办法是:先创建B对象,装配好bean,然后把B注入A,继续完成A的装配.

三、容器初始化过程的源码分析

  我们从ApplicationContext的构造函数开始,如下代码: 

  1.   /**
  2. * Create a new ClassPathXmlApplicationContext with the given parent,
  3. * loading the definitions from the given XML files.
  4. * @param configLocations array of resource locations
  5. * @param refresh whether to automatically refresh the context,
  6. * loading all bean definitions and creating all singletons. --->加载所有bean的定义信息,创建所有单例bean
  7. * Alternatively, call refresh manually after further configuring the context.
  8. * @param parent the parent context
  9. * @throws BeansException if context creation failed
  10. * @see #refresh()
  11. */
  12. public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
  13. throws BeansException {
  14.  
  15. super(parent);
         // 解析给定的配置文件,完成加载所有bean的定义信息的操作
  16. setConfigLocations(configLocations);
  17. if (refresh) {
           // refresh容器,完成创建单例bean的操作
  18. refresh();
  19. }
  20. }

  构造方法的注释上写的so nice.接下来,看加载bean的定义信息的过程,setConfigLocations()是在父类中实现的,接收到配置文件以后,容器开始解析配置文件.经过一系列的调用,会调用org.springframework.beans.factory.xml.XmlBeanDefinitionReader的doLoadBeanDefinitions(),到这里终于看到Document,下面是该方法的源码:

  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. */
  8. protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
  9. throws BeanDefinitionStoreException {
  10. try {
  11. int validationMode = getValidationModeForResource(resource);
  12. // 取得Document对象
  13. Document doc = this.documentLoader.loadDocument(
  14. inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
  15. // 从Document对象中解析bean的定义信息
  16. return registerBeanDefinitions(doc, resource);
  17. }
  18. catch (BeanDefinitionStoreException ex) {
  19. throw ex;
  20. }
         // ...各种异常的处理
  21. }

  registerBeanDefinitions()又会经过一系列的检查和处理,然后调用

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader的doRegisterBeanDefinitions(root)方法进行处理,这部分会从bean元素中解析出bean的定义信息,源代码如下:
  

  1. /**
  2. * Register each bean definition within the given root {@code <beans/>} element.
  3. * @throws IllegalStateException if {@code <beans profile="..."} attribute is present
  4. * and Environment property has not been set
  5. * @see #setEnvironment
  6. */
  7. protected void doRegisterBeanDefinitions(Element root) {
  8. String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
  9. if (StringUtils.hasText(profileSpec)) {
  10. Assert.state(this.environment != null, "environment property must not be null");
  11. String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
  12. if (!this.environment.acceptsProfiles(specifiedProfiles)) {
  13. return;
  14. }
  15. }
  16.  
  17. // any nested <beans> elements will cause recursion in this method. In
  18. // order to propagate and preserve <beans> default-* attributes correctly,
  19. // keep track of the current (parent) delegate, which may be null. Create
  20. // the new (child) delegate with a reference to the parent for fallback purposes,
  21. // then ultimately reset this.delegate back to its original (parent) reference.
  22. // this behavior emulates a stack of delegates without actually necessitating one.
  23. BeanDefinitionParserDelegate parent = this.delegate;
  24. this.delegate = createHelper(readerContext, root, parent);
  25.  
  26. preProcessXml(root);
  27. // 重点部分,解析bean的定义信息
  28. parseBeanDefinitions(root, this.delegate);
  29. postProcessXml(root);
  30.  
  31. this.delegate = parent;
  32. }
  33.   
  34.   /**
  35. * Parse the elements at the root level in the document:
  36. * "import", "alias", "bean".
  37. * @param root the DOM root element of the document
  38. */
  39. protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
  40. if (delegate.isDefaultNamespace(root)) {
  41. NodeList nl = root.getChildNodes();
  42. for (int i = 0; i < nl.getLength(); i++) {
  43. Node node = nl.item(i);
  44. if (node instanceof Element) {
  45. Element ele = (Element) node;
  46. if (delegate.isDefaultNamespace(ele)) {
  47. parseDefaultElement(ele, delegate); // 重点:解析bean元素
  48. }
  49. else {
  50. delegate.parseCustomElement(ele); // 重点:解析其他元素,例如:<context<context:component-scan> or <annotation:config/>
  51. }
  52. }
  53. }
  54. }
  55. else {
  56. delegate.parseCustomElement(root);
  57. }
  58. }

  到这里,终于到了关键的地方,如果bean是在配置文件中配置的,由parseDefaultElement(ele, delegate)处理bean元素的解析,如果是注解配置,parseCustomElement(ele)会扫描包下的class文件,并完成解析.我们先看配置文件中bean元素的解析方式。

  1. private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
  2. if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
  3. importBeanDefinitionResource(ele);
  4. }
  5. else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
  6. processAliasRegistration(ele);
  7. }
  8. else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
  9.       // 重点
  10. processBeanDefinition(ele, delegate);
  11. }
  12. else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
  13. // recurse
  14. doRegisterBeanDefinitions(ele);
  15. }
  16. }
  17.  
  18.   /**
  19. * Process the given bean element, parsing the bean definition
  20. * and registering it with the registry.
  21. */
  22. protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
  23.      // 获取bean的定义信息,用BeanDefinitionHodler对象封装
  24. BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
  25. if (bdHolder != null) {
  26. bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
  27. try {
  28. // Register the final decorated instance.---》关键,将bean的定义信息保存到容器
  29. BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
  30. }
  31. catch (BeanDefinitionStoreException ex) {
  32. getReaderContext().error("Failed to register bean definition with name '" +
  33. bdHolder.getBeanName() + "'", ele, ex);
  34. }
  35. // Send registration event.
  36. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
  37. }
  38. }

  接下来就是调用org.springframework.beans.factory.support.BeanDefinitionReaderUtils的registerBeanDefinition()保存bean定义信息到容器的方法了.

  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 aliase : aliases) {
  19. registry.registerAlias(beanName, aliase);
  20. }
  21. }
  22. }

  ok,来看最终的保存代码:

org.springframework.beans.factory.support.DefaultListableBeanFactory中的registerBeanDefinition();先看DefaultListableBeanFactory保存bean定义信息的Map的声明:
  

  1. /** Map of bean definition objects, keyed by bean name */
  2. private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();

    /** List of bean definition names, in registration order */
    private final List<String> beanDefinitionNames = new ArrayList<String>();

  保存bean定义信息的方法:

  1.   //---------------------------------------------------------------------
  2. // Implementation of BeanDefinitionRegistry interface
  3. //---------------------------------------------------------------------
  4.  
  5. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
  6. throws BeanDefinitionStoreException {
  7.  
  8. Assert.hasText(beanName, "Bean name must not be empty");
  9. Assert.notNull(beanDefinition, "BeanDefinition must not be null");
  10.  
  11. if (beanDefinition instanceof AbstractBeanDefinition) {
  12. try {
  13. ((AbstractBeanDefinition) beanDefinition).validate();
  14. }
  15. catch (BeanDefinitionValidationException ex) {
  16. throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
  17. "Validation of bean definition failed", ex);
  18. }
  19. }
  20.     // 保存bean定义信息,线程同步
  21. synchronized (this.beanDefinitionMap) {
          // 判断当前bean的定义信息是否已经保存
  22. Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
  23. if (oldBeanDefinition != null) {
  24. if (!this.allowBeanDefinitionOverriding) {
  25. throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
  26. "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
  27. "': There is already [" + oldBeanDefinition + "] bound.");
  28. }
  29. else {
  30. if (this.logger.isInfoEnabled()) {
  31. this.logger.info("Overriding bean definition for bean '" + beanName +
  32. "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
  33. }
  34. }
  35. }
  36. else {
             // 保存beanName
  37. this.beanDefinitionNames.add(beanName);
  38. this.frozenBeanDefinitionNames = null;
  39. }
           // 保存beanName和bean的定义信息到Map
  40. this.beanDefinitionMap.put(beanName, beanDefinition);
  41.      
  1. resetBeanDefinition(beanName);
  2. }
  3. }

上面就是spring解析配置文件中的bean定义信息,然后保存beanName和bean定义信息到Map中.这个过程主要就是xml的解析.接下来我们看spring是如何解析注解方式配置的bean.回到parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)方法,现在重点关注:delegate.parseCustomElement(ele)方法.如果我们在配置文件用<context:component-scan  base-package="">方式来指定自动扫描的包,之后就会调用org.springframework.context.annotation.ComponentScanBeanDefinitionParser的parse().下面是parse()方法的源代码:  

  1. public BeanDefinition parse(Element element, ParserContext parserContext) {
         // 解析<context:component-scan元素,获取base-package
  2. String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE),
  3. ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
  4.  
  5. // Actually scan for bean definitions and register them.
  6. ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
         //重点: 扫描basePackage下所有的class文件,读取bean的定义信息
  7. Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
  8. registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
  9.  
  10. return null;
  11. }

重点关注scanner.doScan(basePackges)方法,该方法完成整个核心操作--->根据包名获取包下所有的class的定义信息.直接看org.springframework.context.annotation.ClassPathBeanDefinitionScanner的scan():注意,看源码时一定要多关注注释,例如下面方法上的注释就非常有意义.

  1.   /**
  2. * Perform a scan within the specified base packages,
  3. * returning the registered bean definitions.
  4. * <p>This method does <i>not</i> register an annotation config processor
  5. * but rather leaves this up to the caller.
  6. * @param basePackages the packages to check for annotated classes
  7. * @return set of beans registered if any for tooling registration purposes (never {@code null})
  8. */
  9. protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
  10. Assert.notEmpty(basePackages, "At least one base package must be specified");
  11. Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
  12. for (String basePackage : basePackages) { // 遍历每一个basepackages
           // 1.获取basePackage下bean的定义信息
  13. Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
  14. for (BeanDefinition candidate : candidates) {
             //2.根据扫描的信息,解析bean的一些定义信息
  15. ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
  16. candidate.setScope(scopeMetadata.getScopeName());
  17. String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
  18. if (candidate instanceof AbstractBeanDefinition) {
  19. postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
  20. }
  21. if (candidate instanceof AnnotatedBeanDefinition) {
  22. AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
  23. }
  24. if (checkCandidate(beanName, candidate)) {
  25. BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
  26. definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
  27. beanDefinitions.add(definitionHolder);
                // 3.将bean的定义信息添加到容器中
  28. registerBeanDefinition(definitionHolder, this.registry);
  29. }
  30. }
  31. }
  32. return beanDefinitions;
  33. }

  第1个步骤我们核心关注点,它完成从文件系统中读取class文件的操作,第3个步骤在之前已经说了,就是保存bean的定义信息到容器的DefaultListableBeanFactory的beanDefinitionMap 中.重点关注第1个步骤,看findCandidateComponents()的源代码:

  1. /**
  2. * Scan the class path for candidate components.
  3. * @param basePackage the package to check for annotated classes
  4. * @return a corresponding Set of autodetected bean definitions
  5. */
  6. public Set<BeanDefinition> findCandidateComponents(String basePackage) {
  7. Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
  8. try {
  9. String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
  10. resolveBasePackage(basePackage) + "/" + this.resourcePattern;
           // 1.获取包下的class文件路径,例如E:\Program Files (x86)\MyEclipse10\workplace2\spr\bin\cn\jack\domain\User.class,
           // 每一个class文件的路径封装成Resource对象.
  11. Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
  12. boolean traceEnabled = logger.isTraceEnabled();
  13. boolean debugEnabled = logger.isDebugEnabled();
  14. for (Resource resource : resources) {
  15. if (traceEnabled) {
  16. logger.trace("Scanning " + resource);
  17. }
  18. if (resource.isReadable()) {
  19. try {
                  // 2.使用asm框架读取class文件,获取类的定义信息
  20. MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
  21. if (isCandidateComponent(metadataReader)) {
  22. ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
  23. sbd.setResource(resource);
  24. sbd.setSource(resource);
  25. if (isCandidateComponent(sbd)) {
  26. if (debugEnabled) {
  27. logger.debug("Identified candidate component class: " + resource);
  28. }
  29. candidates.add(sbd);
  30. }
  31. else {
  32. if (debugEnabled) {
  33. logger.debug("Ignored because not a concrete top-level class: " + resource);
  34. }
  35. }
  36. }
  37. else {
  38. if (traceEnabled) {
  39. logger.trace("Ignored because not matching any filter: " + resource);
  40. }
  41. }
  42. }
  43. catch (Throwable ex) {
  44. throw new BeanDefinitionStoreException(
  45. "Failed to read candidate component class: " + resource, ex);
  46. }
  47. }
  48. else {
  49. if (traceEnabled) {
  50. logger.trace("Ignored because not readable: " + resource);
  51. }
  52. }
  53. }
  54. }
  55. catch (IOException ex) {
  56. throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
  57. }
         //3.返回benadefinition集合
  58. return candidates;
  59. }

第1个步骤主要是解析文件路径,然后遍历文件夹获取每个class文件的地址;第2个步骤用asm框架来读取class文件获取类的信息封装成BeanDefinition对象.

第2个步骤最后调用的是org.springframework.core.type.classreading.SimpleMetadataReader的构造函数,下面是该类的部分源代码:

  1. final class SimpleMetadataReader implements MetadataReader {
  2.  
  3. private final Resource resource;
  4. private final ClassMetadata classMetadata;
  5. private final AnnotationMetadata annotationMetadata;
  6.  
  7. SimpleMetadataReader(Resource resource, ClassLoader classLoader) throws IOException {
  8. InputStream is = resource.getInputStream();
  9. ClassReader classReader = null;
  10. try {
           // asm框架读取class文件
  11. classReader = new ClassReader(is);
  12. } finally {
  13. is.close();
  14. }
  15.     // 采用访问者模式来获取class类信息
  16. AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader);
  17. classReader.accept(visitor, true);
  18.  
  19. this.annotationMetadata = visitor;
  20. // (since AnnotationMetadataReader extends ClassMetadataReadingVisitor)
  21. this.classMetadata = visitor;
  22. this.resource = resource;
  23. }

ClassReader是asm框架中核心类,具体用法可以参考asm的官网.

上面说的过程就是spring容器加载bean定义信息的过程.过程很长,但实现原理却并不复杂.

2. 初始化单例bean的过程

  上面分析了spring容器加载bean定义信息的过程,接下来分析bean的初始化以及创建bean的过程.回到ApplicationContext中的构造函数,入口为refresh().refresh方法在父类中实现的。下面是AbstractApplicationContext类refresh()方法的源代码:

  1. public void refresh() throws BeansException, IllegalStateException {
  2. synchronized (this.startupShutdownMonitor) { // 线程同步
  3. // Prepare this context for refreshing.
  4. prepareRefresh();
  5.  
  6. // Tell the subclass to refresh the internal bean factory.
  7. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  8.  
  9. // Prepare the bean factory for use in this context.
  10. prepareBeanFactory(beanFactory);
  11.  
  12. try {
  13. // Allows post-processing of the bean factory in context subclasses.
  14. postProcessBeanFactory(beanFactory);// 容器的后处理器
  15.  
  16. // Invoke factory processors registered as beans in the context.
  17. invokeBeanFactoryPostProcessors(beanFactory);//调用容器的后处理器
  18.  
  19. // Register bean processors that intercept bean creation.
  20. registerBeanPostProcessors(beanFactory);//注册bean的后处理器
  21.  
  22. // Initialize message source for this context.
  23. initMessageSource();
  24.  
  25. // Initialize event multicaster for this context.
  26. initApplicationEventMulticaster();
  27.  
  28. // Initialize other special beans in specific context subclasses.
  29. onRefresh();
  30.  
  31. // Check for listener beans and register them.
  32. registerListeners();
  33.  
  34. // Instantiate all remaining (non-lazy-init) singletons.
  35. finishBeanFactoryInitialization(beanFactory);// 重点,注释写的so nice,初始化所有单例bean
  36.  
  37. // Last step: publish corresponding event.
  38. finishRefresh();
  39. }
  40.  
  41. catch (BeansException ex) {
  42. // Destroy already created singletons to avoid dangling resources.
  43. destroyBeans();
  44.  
  45. // Reset 'active' flag.
  46. cancelRefresh(ex);
  47.  
  48. // Propagate exception to caller.
  49. throw ex;
  50. }
  51. }
  52. }

后处理器是一种特殊bean,用于完成一些自身操作.

容器后处理器:对容器本身进行处理,在容器实例化其他任何Bean之前读取配置文件的元数据并可能修改这些数据.PropertyPlaceholderConfigurer就是一个容器后处理器,用于完成beans.xml中引入其他配置文件中内容操作.

Bean后处理器:即当Spring容器创建完Bean实例之后对bean进行一些处理,例如:完成bean的装配等操作。

回到refresh()方法,重点关注:finishBeanFactoryInitialization(beanFactory);这个方法会调用DefaultListableBeanFactory.preInstantiateSingletons方法.

  1. public void preInstantiateSingletons() throws BeansException {
  2. if (this.logger.isInfoEnabled()) {
  3. this.logger.info("Pre-instantiating singletons in " + this);
  4. }
  5. synchronized (this.beanDefinitionMap) { // 线程同步
  6. // Iterate over a copy to allow for init methods which in turn register new bean definitions.
  7. // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
  8. List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
  9. for (String beanName : beanNames) {// 遍历beanNames
  10. RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
  11. if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {//单例非延迟实例的bean
  12. if (isFactoryBean(beanName)) { // 工厂bean.FactoryBean接口的子类
  13. final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
  14. boolean isEagerInit;
  15. if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
  16. isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
  17. public Boolean run() {
  18. return ((SmartFactoryBean) factory).isEagerInit();
  19. }
  20. }, getAccessControlContext());
  21. }
  22. else {//普通bean
  23. isEagerInit = (factory instanceof SmartFactoryBean &&
  24. ((SmartFactoryBean) factory).isEagerInit());
  25. }
  26. if (isEagerInit) {
  27. getBean(beanName);
  28. }
  29. }
  30. else {
  31. getBean(beanName); // 从容器中获取bean,如果没有创建,并完成装配
  32. }
  33. }
  34. }
  35. }
  36. }

getBean(beanName)方法会调用doGetBean方法.这是个很关键的地方,切记注释很重要

  1. /**
  2. * Return an instance, which may be shared or independent, of the specified bean.
  3. * @param name the name of the bean to retrieve
  4. * @param requiredType the required type of the bean to retrieve
  5. * @param args arguments to use if creating a prototype using explicit arguments to a
  6. * static factory method. It is invalid to use a non-null args value in any other case.
  7. * @param typeCheckOnly whether the instance is obtained for a type check,
  8. * not for actual use
  9. * @return an instance of the bean
  10. * @throws BeansException if the bean could not be created
  11. */
  12. @SuppressWarnings("unchecked")
  13. protected <T> T doGetBean(
  14. final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
  15. throws BeansException {
  16.  
  17. final String beanName = transformedBeanName(name);
  18. Object bean;
  19.  
  20. // Eagerly check singleton cache for manually registered singletons.
  21. Object sharedInstance = getSingleton(beanName);
  22. if (sharedInstance != null && args == null) { //bean已创建,调用方法返回该bean
  23. if (logger.isDebugEnabled()) {
  24. if (isSingletonCurrentlyInCreation(beanName)) {
  25. logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
  26. "' that is not fully initialized yet - a consequence of a circular reference");
  27. }
  28. else {
  29. logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
  30. }
  31. }
           //如果是工厂bean,则返回beanFactory.getObject(),普通bean直接返回sharedInstance
  32. bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  33. }
  34.  
  35. else { //bean未创建
  36. // Fail if we're already creating this bean instance:
  37. // We're assumably within a circular reference.
  38. if (isPrototypeCurrentlyInCreation(beanName)) {
  39. throw new BeanCurrentlyInCreationException(beanName);
  40. }
  41.  
  42. // Check if bean definition exists in this factory.
  43. BeanFactory parentBeanFactory = getParentBeanFactory();
           // 检查父容器是否已经创建该bean,有则从父容器获取bean返回
  44. if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
  45. // Not found -> check parent.
  46. String nameToLookup = originalBeanName(name);
  47. if (args != null) {
  48. // Delegation to parent with explicit args.
  49. return (T) parentBeanFactory.getBean(nameToLookup, args);
  50. }
  51. else {
  52. // No args -> delegate to standard getBean method.
  53. return parentBeanFactory.getBean(nameToLookup, requiredType);
  54. }
  55. }
  56.  
  57. if (!typeCheckOnly) {
  58. markBeanAsCreated(beanName);
  59. }
  60.  
  61. final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
  62. checkMergedBeanDefinition(mbd, beanName, args);
  63.  
  64. // Guarantee initialization of beans that the current bean depends on.
  65. String[] dependsOn = mbd.getDependsOn();
  66. if (dependsOn != null) {
  67. for (String dependsOnBean : dependsOn) {
  68. getBean(dependsOnBean);
  69. registerDependentBean(dependsOnBean, beanName);
  70. }
  71. }
  72.  
  73. // Create bean instance.---》创建单例bean
  74. if (mbd.isSingleton()) {
  75. sharedInstance = getSingleton(beanName, new ObjectFactory() {
  76. public Object getObject() throws BeansException {
  77. try {
  78. return createBean(beanName, mbd, args);// ---> 创建bean的方法
  79. }
  80. catch (BeansException ex) {
  81. // Explicitly remove instance from singleton cache: It might have been put there
  82. // eagerly by the creation process, to allow for circular reference resolution.
  83. // Also remove any beans that received a temporary reference to the bean.
  84. destroySingleton(beanName);
  85. throw ex;
  86. }
  87. }
  88. });
             // 返回创建的单例bean
  89. bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
  90. }
  91.  
  92. else if (mbd.isPrototype()) { // 创建原型bean,scope="prototype"
  93. // It's a prototype -> create a new instance.
  94. Object prototypeInstance = null;
  95. try {
  96. beforePrototypeCreation(beanName);
  97. prototypeInstance = createBean(beanName, mbd, args);
  98. }
  99. finally {
  100. afterPrototypeCreation(beanName);
  101. }
  102. bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
  103. }
  104.  
  105. else {
  106. String scopeName = mbd.getScope();
  107. final Scope scope = this.scopes.get(scopeName);
  108. if (scope == null) {
  109. throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
  110. }
  111. try {
  112. Object scopedInstance = scope.get(beanName, new ObjectFactory() {
  113. public Object getObject() throws BeansException {
  114. beforePrototypeCreation(beanName);
  115. try {
  116. return createBean(beanName, mbd, args);
  117. }
  118. finally {
  119. afterPrototypeCreation(beanName);
  120. }
  121. }
  122. });
  123. bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
  124. }
  125. catch (IllegalStateException ex) {
  126. throw new BeanCreationException(beanName,
  127. "Scope '" + scopeName + "' is not active for the current thread; " +
  128. "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
  129. ex);
  130. }
  131. }
  132. }
  133.  
  134. // Check if required type matches the type of the actual bean instance.
  135. if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
  136. try {
  137. return getTypeConverter().convertIfNecessary(bean, requiredType);
  138. }
  139. catch (TypeMismatchException ex) {
  140. if (logger.isDebugEnabled()) {
  141. logger.debug("Failed to convert bean '" + name + "' to required type [" +
  142. ClassUtils.getQualifiedName(requiredType) + "]", ex);
  143. }
  144. throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
  145. }
  146. }
        // 返回bean
  147. return (T) bean;
  148. }

createBean(beanName, mbd, args)方法会调用doCreateBean()完成bean的创建工作,源代码如下:

  1. /**
  2. * Actually create the specified bean. Pre-creation processing has already happened
  3. * at this point, e.g. checking <code>postProcessBeforeInstantiation</code> callbacks.
  4. * <p>Differentiates between default bean instantiation, use of a
  5. * factory method, and autowiring a constructor.
  6. * @param beanName the name of the bean
  7. * @param mbd the merged bean definition for the bean
  8. * @param args arguments to use if creating a prototype using explicit arguments to a
  9. * static factory method. This parameter must be <code>null</code> except in this case.
  10. * @return a new instance of the bean
  11. * @throws BeanCreationException if the bean could not be created
  12. * @see #instantiateBean
  13. * @see #instantiateUsingFactoryMethod
  14. * @see #autowireConstructor
  15. */
  16. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
  17. // Instantiate the bean.
  18. BeanWrapper instanceWrapper = null;
  19. if (mbd.isSingleton()) {
  20. instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  21. }
  22. if (instanceWrapper == null) {
           // 1.创建bean的包装类,装饰设计模式
  23. instanceWrapper = createBeanInstance(beanName, mbd, args);
  24. }
  25. final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
  26. Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
  27.  
  28. // Allow post-processors to modify the merged bean definition.
  29. synchronized (mbd.postProcessingLock) {
  30. if (!mbd.postProcessed) {
  31. applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
  32. mbd.postProcessed = true;
  33. }
  34. }
  35.  
  36. // Eagerly cache singletons to be able to resolve circular references
  37. // even when triggered by lifecycle interfaces like BeanFactoryAware.
  38. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
  39. isSingletonCurrentlyInCreation(beanName));
  40. if (earlySingletonExposure) {
  41. if (logger.isDebugEnabled()) {
  42. logger.debug("Eagerly caching bean '" + beanName +
  43. "' to allow for resolving potential circular references");
  44. }
  45. addSingletonFactory(beanName, new ObjectFactory() {
  46. public Object getObject() throws BeansException {
  47. return getEarlyBeanReference(beanName, mbd, bean);
  48. }
  49. });
  50. }
  51.  
  52. // Initialize the bean instance.
  53. Object exposedObject = bean;
  54. try {
           //2.装配bean
  55. populateBean(beanName, mbd, instanceWrapper);
  56. if (exposedObject != null) {
  57. exposedObject = initializeBean(beanName, exposedObject, mbd);
  58. }
  59. }
  60. catch (Throwable ex) {
  61. if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
  62. throw (BeanCreationException) ex;
  63. }
  64. else {
  65. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
  66. }
  67. }
  68.  
  69. if (earlySingletonExposure) {
  70. Object earlySingletonReference = getSingleton(beanName, false);
  71. if (earlySingletonReference != null) {
  72. if (exposedObject == bean) {
  73. exposedObject = earlySingletonReference;
  74. }
  75. else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
  76. String[] dependentBeans = getDependentBeans(beanName);
  77. Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
  78. for (String dependentBean : dependentBeans) {
  79. if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
  80. actualDependentBeans.add(dependentBean);
  81. }
  82. }
  83. if (!actualDependentBeans.isEmpty()) {
  84. throw new BeanCurrentlyInCreationException(beanName,
  85. "Bean with name '" + beanName + "' has been injected into other beans [" +
  86. StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
  87. "] in its raw version as part of a circular reference, but has eventually been " +
  88. "wrapped. This means that said other beans do not use the final version of the " +
  89. "bean. This is often the result of over-eager type matching - consider using " +
  90. "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
  91. }
  92. }
  93. }
  94. }
  95.  
  96. // Register bean as disposable.
  97. try {
  98. registerDisposableBeanIfNecessary(beanName, bean, mbd);
  99. }
  100. catch (BeanDefinitionValidationException ex) {
  101. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
  102. }
  103.      //3.返回
  104. return exposedObject;
  105. }

首先看第1个步骤,这个步骤中会创建bean实例和bean的包装类,这里使用了装饰设计模式.创建bean的实例过程比较简单,如果配置bean时指定了bean的创建方法 factory-method,就用factory-method创建bean实例,默认会使用无参构造函数创建bean实例.这部分重点关注装配bean的过程.

  1. /**
  2. * Create a new instance for the specified bean, using an appropriate instantiation strategy:
  3. * factory method, constructor autowiring, or simple instantiation.
  4. * @param beanName the name of the bean
  5. * @param mbd the bean definition for the bean
  6. * @param args arguments to use if creating a prototype using explicit arguments to a
  7. * static factory method. It is invalid to use a non-null args value in any other case.
  8. * @return BeanWrapper for the new instance
  9. * @see #instantiateUsingFactoryMethod
  10. * @see #autowireConstructor
  11. * @see #instantiateBean
  12. */
  13. protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
  14. // Make sure bean class is actually resolved at this point.
  15. Class beanClass = resolveBeanClass(mbd, beanName);
  16.  
  17. if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
  18. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  19. "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
  20. }
  21.  
  22. if (mbd.getFactoryMethodName() != null) {// 使用工厂方法创建bean,<bean factory-method="">
  23. return instantiateUsingFactoryMethod(beanName, mbd, args);
  24. }
  25.  
  26. // Shortcut when re-creating the same bean...
  27. boolean resolved = false;
  28. boolean autowireNecessary = false;
  29. if (args == null) {
  30. synchronized (mbd.constructorArgumentLock) {
  31. if (mbd.resolvedConstructorOrFactoryMethod != null) {
  32. resolved = true;
  33. autowireNecessary = mbd.constructorArgumentsResolved;
  34. }
  35. }
  36. }
  37. if (resolved) {
  38. if (autowireNecessary) {
  39. return autowireConstructor(beanName, mbd, null, null);
  40. }
  41. else {
  42. return instantiateBean(beanName, mbd);
  43. }
  44. }
  45.  
  46. // Need to determine the constructor...
  47. Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
  48. if (ctors != null ||
  49. mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
  50. mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
  51. return autowireConstructor(beanName, mbd, ctors, args);
  52. }
  53.     // 用默认的构造函数创建bean,反射获取构造函数,constructor.newInstance()创建bean.
  54. // No special handling: simply use no-arg constructor.
  55. return instantiateBean(beanName, mbd);
  56. }

  现在来看装配bean的过程,这个过程完成注入bean的依赖对象,如果bean是在配置文件配置的,则把从xml中解析出来的属性注入给bean实例,如果是用注解配置的依赖(@Resource 或者@AutoWired),则会解析bean的字段或者方法上的注解,根据这些注解找到对应的依赖,如果依赖对象已经创建,就直接注入依赖,否则,先创建依赖对象,在完成注入操作.

  1. /**
  2. * Populate the bean instance in the given BeanWrapper with the property values
  3. * from the bean definition.
  4. * @param beanName the name of the bean
  5. * @param mbd the bean definition for the bean
  6. * @param bw BeanWrapper with bean instance
  7. */
  8. protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
  9. PropertyValues pvs = mbd.getPropertyValues();
  10.  
  11. if (bw == null) {
  12. if (!pvs.isEmpty()) {
  13. throw new BeanCreationException(
  14. mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
  15. }
  16. else {
  17. // Skip property population phase for null instance.
  18. return;
  19. }
  20. }
  21.  
  22. // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
  23. // state of the bean before properties are set. This can be used, for example,
  24. // to support styles of field injection.
  25. boolean continueWithPropertyPopulation = true;
  26.  
  27. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  28. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  29. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  30. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  31. if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
  32. continueWithPropertyPopulation = false;
  33. break;
  34. }
  35. }
  36. }
  37. }
  38.  
  39. if (!continueWithPropertyPopulation) {
  40. return;
  41. }
  42.      // 根据beanName或者type完成自动装配
  43. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
  44. mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
  45. MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
  46.  
  47. // Add property values based on autowire by name if applicable.
  48. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
  49. autowireByName(beanName, mbd, bw, newPvs);
  50. }
  51.  
  52. // Add property values based on autowire by type if applicable.
  53. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
  54. autowireByType(beanName, mbd, bw, newPvs);
  55. }
  56.  
  57. pvs = newPvs;
  58. }
  59.  
  60. boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
  61. boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
  62.      // 调用bean后处理器
  63. if (hasInstAwareBpps || needsDepCheck) {
  64. PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
  65. if (hasInstAwareBpps) {
  66. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  67. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  68. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                  // 重点:获取bean要装配的属性和属性值
  69. pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
  70. if (pvs == null) {
  71. return;
  72. }
  73. }
  74. }
  75. }
  76. if (needsDepCheck) {
  77. checkDependencies(beanName, mbd, filteredPds, pvs);
  78. }
  79. }
  80.      // 给bean的属性赋值
  81. applyPropertyValues(beanName, mbd, bw, pvs);
  82. }

  InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口,能在bean初始化前后对bean进行处理.InstantiationAwareBeanPostProcessor有以下几个子类:

  

  @Resource注解注入依赖的工作就是由CommonAnnotationBeanPostProcessor完成的.下面是该类postProcessPropertyValues()的源码:

  1. public PropertyValues postProcessPropertyValues(
  2. PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
  3.      //1.根据bean的字节码,遍历所有的字段和方法,获取需要注入的字段或者方法
  4. InjectionMetadata metadata = findResourceMetadata(bean.getClass());
  5. try {
           //2.从容器中查找依赖对象,并赋值给相应的字段,完成bean的装配
  6. metadata.inject(bean, beanName, pvs);
  7. }
  8. catch (Throwable ex) {
  9. throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
  10. }
  11. return pvs;
  12. }

  第1个步骤主要就是根据字节码获取所有字段和方法,然后遍历查找有@Resource注解的字段或方法以及依赖bean的beanName,第2个步骤从容器中依赖对象的beanName(@Resource的name属性值),如果容器中没有该依赖对象就创建,有的话就直接获取,并赋值给bean的属性.这样,就通过bean的后处理器完成了bean的装配过程.

  到这里,容器的启动过程就完成了,此时就可以对外提供服务了.上面就是本人对spring容器部分源码学习的一些总结.日后,了解更多会不定时更新上来!

  

  

Spring bean是如何加载的

Spring bean是如何加载的

加载bean的主要逻辑

在AbstractBeanFactory中doGetBean对加载bean的不同情况进行拆分处理,并做了部分准备工作
具体如下

  1. 获取原始bean name
    1. 根据alia获取原始bean name
    2. 去除FactoryBean时的& [如果是需要获取FactoryBean自省,配置时需要在bean name前添加&]
  2. 尝试从缓存中获取实例
    1. 如果获取到实例,还要委托getObjectForBeanInstance解决FactoryBean的场景,就是调用getObject
  3. 判断原型场景的循环依赖问题,如果是原型同时bean又正在创建,说明是循环依赖,那直接抛异常,spring不尝试解决原型的循环依赖
  4. 如果在本容器中没有定义该bean,需要去父容器查找
    • 如果有参数,结合参数初始化
    • 如果没有参数,需要结合类型初始化,这边的调用是这个分支(当然这边一样没有类型)
  5. 如果不是类型检查,这边需要标记bean正在实例化
  6. bean实例化的准备工作
    1. 合并父bean的定义,并转化GenericBeanDefinition为RootBeanDefinition
    2. 校验BeanDefinition,如果是抽象类或者非原型带参数抛异常[这边注释说的是只有原型才可以配置构造方法的参数]
    3. 解决bean的依赖
      • 注册依赖的bean
      • 递归调用getBean实例化依赖bean
  7. 创建单例的实例
    • 为解决循环依赖问题,这边使用ObjectFactory在实例化前先暴露bean
    • 老规矩,需要委托getObejctForBeanInstance解决FactoryBean的问题
  8. 创建原型实例
    • 创建前的准备工作,使用prototypesCurrentlyInCreation标记bean正在实例化
    • 委托createBean实例化bean
    • 创建后的善后工作,从prototypesCurrentlyInCreation中删除标记
    • 老规矩,委托getObjectForBeanInstance解决工厂方法的问题
  9. 创建其他scope的实例,这边的逻辑结合了单例跟原型的处理逻辑,即使用解决循环依赖的ObjectFactory也使用prototypeCreation的标记
    • 获取作用域scope,并校验是否已配置
    • 使用ObjectFactory提早暴露实例
    • 标记bean正在创建并委托createBean实例化
    • 又是委托getObjectForBeanInstance解决工厂方法问题
  10. 最后需要对创建的实例进行类型校验,如果不一致,这边还需要委托TypeConverter进行类型装换

AbstractBeanFactory

  1. @Override
  2. public Object getBean(String name) throws BeansException {
  3. return doGetBean(name, null, null, false);
  4. }
  5. protected <T> T doGetBean(
  6. final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
  7. throws BeansException {
  8. // 获取原始的bean name,去除&,解决alias问题
  9. final String beanName = transformedBeanName(name);
  10. Object bean;
  11. // 尝试从缓存中获取bean
  12. // Eagerly check singleton cache for manually registered singletons.
  13. Object sharedInstance = getSingleton(beanName);
  14. if (sharedInstance != null && args == null) {
  15. if (logger.isDebugEnabled()) {
  16. if (isSingletonCurrentlyInCreation(beanName)) {
  17. // ...
  18. }
  19. else {
  20. logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
  21. }
  22. }
  23. // 如果从缓存中或得bean,还需要判断是否是FactoryBean,并调用getObejct
  24. bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  25. }
  26. else {
  27. // 如果是原型scope,这边又是正在创建,说明有循环依赖,而原型的循环依赖Spring是不解决的
  28. // Fail if we're already creating this bean instance:
  29. // We're assumably within a circular reference.
  30. if (isPrototypeCurrentlyInCreation(beanName)) {
  31. throw new BeanCurrentlyInCreationException(beanName);
  32. }
  33. // 如果当前容器没有配置bean,那么去父容器查找
  34. // Check if bean definition exists in this factory.
  35. BeanFactory parentBeanFactory = getParentBeanFactory();
  36. if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
  37. // Not found -> check parent.
  38. String nameToLookup = originalBeanName(name);
  39. if (args != null) {
  40. // Delegation to parent with explicit args.
  41. return (T) parentBeanFactory.getBean(nameToLookup, args);
  42. }
  43. else {
  44. // No args -> delegate to standard getBean method.
  45. return parentBeanFactory.getBean(nameToLookup, requiredType);
  46. }
  47. }
  48. // 如果不是类型检查,这边需要标记类正在创建
  49. if (!typeCheckOnly) {
  50. markBeanAsCreated(beanName);
  51. }
  52. try {
  53. // 实例化类之前,先去容器中获取配置的bean信息,这边需要将之前的GenericBeanDefinition转化为RootBeanDefinition
  54. // 同时如果父bean的话,需要合并到子bean
  55. final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
  56. checkMergedBeanDefinition(mbd, beanName, args);
  57. // Guarantee initialization of beans that the current bean depends on.
  58. String[] dependsOn = mbd.getDependsOn();
  59. if (dependsOn != null) {
  60. for (String dependsOnBean : dependsOn) {
  61. if (isDependent(beanName, dependsOnBean)) {
  62. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  63. "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
  64. }
  65. // 解决依赖
  66. registerDependentBean(dependsOnBean, beanName);
  67. getBean(dependsOnBean);
  68. }
  69. }
  70. // 创建单例的实例
  71. // Create bean instance
  72. if (mbd.isSingleton()) {
  73. // 单例情况下,为解决循环依赖,在实例化之前,先新建一个ObjectFactory实例
  74. sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
  75. @Override
  76. public Object getObject() throws BeansException {
  77. try {
  78. return createBean(beanName, mbd, args);
  79. }
  80. catch (BeansException ex) {
  81. // Explicitly remove instance from singleton cache: It might have been put there
  82. // eagerly by the creation process, to allow for circular reference resolution.
  83. // Also remove any beans that received a temporary reference to the bean.
  84. destroySingleton(beanName);
  85. throw ex;
  86. }
  87. }
  88. });
  89. bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
  90. }
  91. // 创建原型实例
  92. else if (mbd.isPrototype()) {
  93. // It's a prototype -> create a new instance.
  94. Object prototypeInstance = null;
  95. try {
  96. beforePrototypeCreation(beanName);
  97. prototypeInstance = createBean(beanName, mbd, args);
  98. }
  99. finally {
  100. afterPrototypeCreation(beanName);
  101. }
  102. bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
  103. }
  104. // 创建其他scope的实例
  105. else {
  106. String scopeName = mbd.getScope();
  107. final Scope scope = this.scopes.get(scopeName);
  108. if (scope == null) {
  109. throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
  110. }
  111. try {
  112. // 还是先创建ObejctFactory,只是这边没有处理
  113. Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
  114. @Override
  115. public Object getObject() throws BeansException {
  116. beforePrototypeCreation(beanName);
  117. try {
  118. return createBean(beanName, mbd, args);
  119. }
  120. finally {
  121. afterPrototypeCreation(beanName);
  122. }
  123. }
  124. });
  125. bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
  126. }
  127. catch (IllegalStateException ex) {
  128. throw new BeanCreationException(beanName,
  129. "Scope '" + scopeName + "' is not active for the current thread; " +
  130. "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
  131. ex);
  132. }
  133. }
  134. }
  135. catch (BeansException ex) {
  136. cleanupAfterBeanCreationFailure(beanName);
  137. throw ex;
  138. }
  139. }
  140. // 这边需要对实例进行类型校验,如果与requiredType不一致,需要委托TypeConverter尝试类型转换
  141. // Check if required type matches the type of the actual bean instance.
  142. if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
  143. try {
  144. return getTypeConverter().convertIfNecessary(bean, requiredType);
  145. }
  146. catch (TypeMismatchException ex) {
  147. if (logger.isDebugEnabled()) {
  148. logger.debug("Failed to convert bean '" + name + "' to required type [" +
  149. ClassUtils.getQualifiedName(requiredType) + "]", ex);
  150. }
  151. throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
  152. }
  153. }
  154. return (T) bean;
  155. }

bean实例的缓存分析

上面提到在加载bean的时候,doGetBean首先尝试的是从缓存读取,这边我们来细细分析下缓存具体是如何处理的.

这边逻辑是定义在DefaultSingletonBeanRegistry中,它是AbstractBeanFactory的父类,主要职责是共享实例的注册.
这边虽然定义的是singleton,但是实际使用的时候,处理prototype,其他scope均使用了这边进行缓存.

这边主要是需要理解singletonObjects,singletonFactories,earlySingletonObjects,registeredSingletons这4个变量.

singletonObjects 缓存bean name ->实例

Cache of singleton objects: bean name --> bean instance
这边缓存的是实例

singletonFactories 缓存bean name -->ObjectFactory

Cache of singleton factories: bean name --> ObjectFactory
这边缓存的是为解决循环依赖而准备的ObjectFactory

earlySingletonObjects 缓存提早暴露的实例 bean name -->bean instance

Cache of early singleton objects: bean name --> bean instance
这边缓存的也是实例,只是这边的是为解决循环依赖而提早暴露出来的实例,其实是ObjectFactory

registeredSingletons 已经注册的单例bean name

Set of registered singletons, containing the bean names in registration order
上面三个变量,任意一个添加了,这边都会添加bean name,标记已经注册

4个变量的关系如下:

  • singletonObjects与singletonFactories,earlySingletonObjects,是互斥的.就是一个bean如果在其中任意一个变量中就,不会存在在另一变量中.这三个变量用于记录一个bean的不同状态.
  • 如果bean已经添加到singletonObjects中,那么singltonFactories和earlySinletonObjects都不会考虑
  • singltonFactories中的bean 通过 ObjectFactory的getObject实例化后,添加到earlySingletonObjects

我们从下面几个方法,可以清楚看懂上面4个变量的使用:
DefaultSingletonBeanRegistry

  1. /**
  2. * 添加实例化的bean
  3. * Add the given singleton object to the singleton cache of this factory.
  4. * <p>To be called for eager registration of singletons.
  5. * @param beanName the name of the bean
  6. * @param singletonObject the singleton object
  7. */
  8. protected void addSingleton(String beanName, Object singletonObject) {
  9. synchronized (this.singletonObjects) {
  10. this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
  11. this.singletonFactories.remove(beanName);
  12. this.earlySingletonObjects.remove(beanName);
  13. this.registeredSingletons.add(beanName);
  14. }
  15. }
  16. /**
  17. * 为解决单例的循环依赖,这边注册ObjectFactory
  18. * Add the given singleton factory for building the specified singleton
  19. * if necessary.
  20. * <p>To be called for eager registration of singletons, e.g. to be able to
  21. * resolve circular references.
  22. * @param beanName the name of the bean
  23. * @param singletonFactory the factory for the singleton object
  24. */
  25. protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
  26. Assert.notNull(singletonFactory, "Singleton factory must not be null");
  27. synchronized (this.singletonObjects) {
  28. if (!this.singletonObjects.containsKey(beanName)) {
  29. this.singletonFactories.put(beanName, singletonFactory);
  30. this.earlySingletonObjects.remove(beanName);
  31. this.registeredSingletons.add(beanName);
  32. }
  33. }
  34. }
  35. /**
  36. * 清除实例
  37. * Remove the bean with the given name from the singleton cache of this factory,
  38. * to be able to clean up eager registration of a singleton if creation failed.
  39. * @param beanName the name of the bean
  40. * @see #getSingletonMutex()
  41. */
  42. protected void removeSingleton(String beanName) {
  43. synchronized (this.singletonObjects) {
  44. this.singletonObjects.remove(beanName);
  45. this.singletonFactories.remove(beanName);
  46. this.earlySingletonObjects.remove(beanName);
  47. this.registeredSingletons.remove(beanName);
  48. }
  49. }
  50. /**
  51. * 获取实例时,调用ObejctFactory的getObject 获取实例
  52. * Return the (raw) singleton object registered under the given name.
  53. * <p>Checks already instantiated singletons and also allows for an early
  54. * reference to a currently created singleton (resolving a circular reference).
  55. * @param beanName the name of the bean to look for
  56. * @param allowEarlyReference whether early references should be created or not
  57. * @return the registered singleton object, or {@code null} if none found
  58. */
  59. protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  60. Object singletonObject = this.singletonObjects.get(beanName);
  61. if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
  62. synchronized (this.singletonObjects) {
  63. singletonObject = this.earlySingletonObjects.get(beanName);
  64. if (singletonObject == null && allowEarlyReference) {
  65. ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
  66. if (singletonFactory != null) {
  67. singletonObject = singletonFactory.getObject();
  68. this.earlySingletonObjects.put(beanName, singletonObject);
  69. this.singletonFactories.remove(beanName);
  70. }
  71. }
  72. }
  73. }
  74. return (singletonObject != NULL_OBJECT ? singletonObject : null);
  75. }

BeanPostProcessor Bean实例的初始化前后的自定义修改

BeanPostProcessor接口的行为方法

  1. public interface BeanPostProcessor {
  2.  
  3. /**
  4. * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
  5. * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
  6. * or a custom init-method). The bean will already be populated with property values.
  7. * The returned bean instance may be a wrapper around the original.
  8. * @param bean the new bean instance
  9. * @param beanName the name of the bean
  10. * @return the bean instance to use, either the original or a wrapped one; if
  11. * {@code null}, no subsequent BeanPostProcessors will be invoked
  12. * @throws org.springframework.beans.BeansException in case of errors
  13. * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
  14. */
  15. Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
  16.  
  17. /**
  18. * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
  19. * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
  20. * or a custom init-method). The bean will already be populated with property values.
  21. * The returned bean instance may be a wrapper around the original.
  22. * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
  23. * instance and the objects created by the FactoryBean (as of Spring 2.0). The
  24. * post-processor can decide whether to apply to either the FactoryBean or created
  25. * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
  26. * <p>This callback will also be invoked after a short-circuiting triggered by a
  27. * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
  28. * in contrast to all other BeanPostProcessor callbacks.
  29. * @param bean the new bean instance
  30. * @param beanName the name of the bean
  31. * @return the bean instance to use, either the original or a wrapped one; if
  32. * {@code null}, no subsequent BeanPostProcessors will be invoked
  33. * @throws org.springframework.beans.BeansException in case of errors
  34. * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
  35. * @see org.springframework.beans.factory.FactoryBean
  36. */
  37. Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
  38.  
  39. }

自定义的BeanPostProcessor

  1. package com.wjz.spring;
  2.  
  3. import org.springframework.beans.BeansException;
  4. import org.springframework.beans.factory.config.BeanPostProcessor;
  5.  
  6. import com.wjz.core.CustomInitializable;
  7.  
  8. public class CustomBeanPostProcessor implements BeanPostProcessor {
  9.  
  10. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  11. if (bean instanceof CustomInitializable) {
  12. System.out.println("before init......");
  13. ((CustomInitializable) bean).init();
  14. }
  15. return bean;
  16. }
  17.  
  18. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  19. System.out.println("after init......");
  20. return bean;
  21. }
  22.  
  23. }

自定义的修改

  1. package com.wjz.core;
  2.  
  3. public abstract interface CustomInitializable {
  4.  
  5. abstract void init();
  6. }
  1. package com.wjz.core;
  2.  
  3. public class Realm implements CustomInitializable {
  4.  
  5. public void init() {
  6. System.out.println("init......");
  7. }
  8.  
  9. }

关于Shiro框架对于BeanPostProcessor的使用

LifecycleBeanPostProcessor

  1. public Object postProcessBeforeInitialization(Object object, String name) throws BeansException {
  2. if (object instanceof Initializable) {
  3. try {
  4. if (log.isDebugEnabled()) {
  5. log.debug("Initializing bean [" + name + "]...");
  6. }
  7.  
  8. ((Initializable) object).init();
  9. } catch (Exception e) {
  10. throw new FatalBeanException("Error initializing bean [" + name + "]", e);
  11. }
  12. }
  13. return object;
  14. }
  15.  
  16. /**
  17. * Does nothing - merely returns the object argument immediately.
  18. */
  19. public Object postProcessAfterInitialization(Object object, String name) throws BeansException {
  20. // Does nothing after initialization
  21. return object;
  22. }
  1. public abstract interface org.apache.shiro.util.Initializable {
  2.  
  3. public abstract void init() throws org.apache.shiro.ShiroException;
  4.  
  5. }

AuthenticatingRealm

  1. public final void init() {
  2. //trigger obtaining the authorization cache if possible 如果可能,触发获得授权缓存
  3. getAvailableAuthenticationCache();
  4. onInit();
  5. }
 
 
 
 
 
 

框架-spring源码分析(一)的更多相关文章

  1. spring源码分析之spring-core总结篇

    1.spring-core概览 spring-core是spring框架的基石,它为spring框架提供了基础的支持. spring-core从源码上看,分为6个package,分别是asm,cgli ...

  2. 【Spring源码分析】非懒加载的单例Bean初始化过程(上篇)

    代码入口 上文[Spring源码分析]Bean加载流程概览,比较详细地分析了Spring上下文加载的代码入口,并且在AbstractApplicationContext的refresh方法中,点出了f ...

  3. 【spring源码分析】IOC容器初始化(二)

    前言:在[spring源码分析]IOC容器初始化(一)文末中已经提出loadBeanDefinitions(DefaultListableBeanFactory)的重要性,本文将以此为切入点继续分析. ...

  4. spring源码分析系列 (8) FactoryBean工厂类机制

    更多文章点击--spring源码分析系列 1.FactoryBean设计目的以及使用 2.FactoryBean工厂类机制运行机制分析 1.FactoryBean设计目的以及使用 FactoryBea ...

  5. spring源码分析系列 (3) spring拓展接口InstantiationAwareBeanPostProcessor

    更多文章点击--spring源码分析系列 主要分析内容: 一.InstantiationAwareBeanPostProcessor简述与demo示例 二.InstantiationAwareBean ...

  6. Spring源码分析:非懒加载的单例Bean初始化过程(上)

    上文[Spring源码分析]Bean加载流程概览,比较详细地分析了Spring上下文加载的代码入口,并且在AbstractApplicationContext的refresh方法中,点出了finish ...

  7. 框架-springmvc源码分析(二)

    框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...

  8. 框架-springmvc源码分析(一)

    框架-springmvc源码分析(一) 参考: http://www.cnblogs.com/heavenyes/p/3905844.html#a1 https://www.cnblogs.com/B ...

  9. Spring源码分析专题 —— IOC容器启动过程(上篇)

    声明 1.建议先阅读<Spring源码分析专题 -- 阅读指引> 2.强烈建议阅读过程中要参照调用过程图,每篇都有其对应的调用过程图 3.写文不易,转载请标明出处 前言 关于 IOC 容器 ...

随机推荐

  1. 关于记录cookie引发的问题

    很多时候我们会通过记录cookie的方式来记录用户的最后一次行为,但是对cookie的处理是在js中进行的. 但通常情况下,html.css都要早于js加载完成,并且可能在js生效之前就已经渲染完成了 ...

  2. 微信小程序 --- 选择图片和拍照

    wx.chooseImage 选择图片 / 进行拍照 //获取应用实例 const app = getApp() Page({ data: { onOff:true }, btnclick:funct ...

  3. oneThink添加成功,返回到当前请求地址!

    其实没什么,就一行代码: $this->success('已采纳',$_SERVER['HTTP_REFERER']);

  4. pycharm 和 Anaconda 下的 opencv 安装

    学习真的切忌三天打鱼两天晒网!! 一开始python下的opencv已经都弄好了,中间电脑坏了一次,好久没有接触这个,就全部都忘完了.深感惋惜. 今天又从新安装了一下opencv.在anaconda下 ...

  5. html 标准属性不要用 setAttribute 方法

    html 中有些属性,譬如 checked , autofocus 只要存在就会有效,即使值是 false ,譬如: <input autofocus=false id='test'> & ...

  6. Hadoop讲解

    1.简介 Hadoop是一款开源的大数据通用处理平台,其提供了分布式存储和分布式离线计算,适合大规模数据.流式数据(写一次,读多次),不适合低延时的访问.大量的小文件以及频繁修改的文件. *Hadoo ...

  7. CH5E09 能量相连【区间DP】

    5E09 能量项链 0x5E「动态规划」练习 描述 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数.并且, ...

  8. 服务器和客户端的交互方式(Socket,http协议)和各自特点适用范围

    1 数据传输方式 1.1  Socket传输的定义和其特点 所谓socket通常也称作"套接字",实现服务器和客户端之间的物理连接,并进行数据传输,主要有UDP和TCP两个协议.S ...

  9. Redis缓冲区设置

    对于Redis服务器的输出(也就是命令的返回值)来说,其大小通常是不可控制的.有可能一个简单的命令,能够产生体积庞大的返回数据.另外也有可能因为执行了太多命令,导致产生返回数据的速率超过了往客户端发送 ...

  10. 用virtualenv建立多个Python独立开发环境(转)

    add by zhj: 在virtualenv环境下,安装第三方包时,不要用sudo pip install xxx,要直接用pip install xxx,如果用sudo时,那会安装在原来的系统Py ...