zoukankan      html  css  js  c++  java
  • Spring源码分析之IOC 容器

    Spring启动方式:

      启动spring容器有两种方式,分别是通过配置文件的读取启动,通过JavaConfig配置类启动。

      在使用配置文件启动的时候,我们就需要使用ClassPathXmlApplicationContext("xx.xml")来构建容器,并初始化bean。

    1 public class Test1 {
    2     public static void main(String[] args) {
    3         ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    4         IndexService service = (IndexService) context.getBean("service");
    5         service.query();
    6     }
    7 }

      在使用JavaConfig配置类启动的时候,我们需要使用AnnotationConfigApplicationContext("xx.class")来构建容器,并初始化bean。

    1 public class Test {
    2     public static void main(String[] args) {
    3         //把spring所有的前提环境准备好了,包括spring容器还有类的实例化都完成了。
    4         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyAnnotation.class);
    5         IndexService service = (IndexService)context.getBean("service");
    6         service.query();
    7     }
    8 }

      进入AnnotationConfigApplicationContext类中,查看构造方法。

     1 /**
     2      * 这个构造方法需要传入一个被Javaconfig注解过的配置类
     3      * 然后会把这个被注解了的配置类通过注解读取器读取后进行解析
     4      * @param annotatedClasses
     5      */
     6     public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
     7         //这里由于它有父类,故而会先调用父类的构造方法,然后才会调用自己的构造方法,
     8         //在自己的构造方法中初始化一个读取器和扫描器
     9         this();
    10         //注册单个bean给容器,比如有新加的类可以使用这个方法
    11         //但是注册之后需要手动调用refresh()方法去触发容器解析注解
    12         register(annotatedClasses);
    13         refresh();
    14     }

      进入this()方法,查看自己的构造方法

     1 public AnnotationConfigApplicationContext() {
     2         /**
     3          * 创建一个读取注解的Bean定义读取器
     4          * 什么是Bean定义?BeanDefinition
     5          * BeanDefinition这个类是描述springBean对象的类。
     6          */
     7         this.reader = new AnnotatedBeanDefinitionReader(this);
     8         /**
     9          * 创建一个扫描器,扫描所有加了注解的类
    10          */
    11         this.scanner = new ClassPathBeanDefinitionScanner(this);
    12     }

      进入register()方法,忽略掉封装方法,直接进入AnnotatedBeanDefinitionReader类中的doRegisterBean()方法:

     1 <T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
     2             @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
     3 
     4         AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
     5         if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
     6             return;
     7         }
     8 
     9         abd.setInstanceSupplier(instanceSupplier);
    10         ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    11         abd.setScope(scopeMetadata.getScopeName());
    12         String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    13 
    14         AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    15         /**
    16          * 对属性进行判断
    17          */
    18         if (qualifiers != null) {
    19             for (Class<? extends Annotation> qualifier : qualifiers) {
    20                 if (Primary.class == qualifier) {
    21                     abd.setPrimary(true);
    22                 }
    23                 else if (Lazy.class == qualifier) {
    24                     abd.setLazyInit(true);
    25                 }
    26                 else {
    27                     abd.addQualifier(new AutowireCandidateQualifier(qualifier));
    28                 }
    29             }
    30         }
    31         for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
    32             customizer.customize(abd);
    33         }
    34 
    35         BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    36         definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    37         /**
    38          * 把处理后的bean当做参数,进行注册
    39          */
    40         BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    41     }

      进入BeanDefinitionReaderUtils类中的registerBeanDefinition()方法:

     1 /**
     2      * 向给定的bean工厂注册给定的bean定义
     3      * @param definitionHolder
     4      * @param registry
     5      * @throws BeanDefinitionStoreException
     6      */
     7     public static void registerBeanDefinition(
     8             BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
     9             throws BeanDefinitionStoreException {
    10 
    11         // Register bean definition under primary name.
    12         // 把beanName作为主名,在bean工厂中注册
    13         String beanName = definitionHolder.getBeanName();
    14         //通过DefaultListableBeanFactory工厂进行注册
    15         registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    16 
    17         // Register aliases for bean name, if any.
    18         // 对别名进行处理
    19         String[] aliases = definitionHolder.getAliases();
    20         if (aliases != null) {
    21             for (String alias : aliases) {
    22                 registry.registerAlias(beanName, alias);
    23             }
    24         }
    25     }

      进入DefaultListableBeanFactory类的registerBeanDefinition()方法进行注册。

        /** Map of bean definition objects, keyed by bean name. */

        private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

        /** List of bean definition names, in registration order. */

        private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

     1 @Override
     2     public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
     3             throws BeanDefinitionStoreException {
     4 
     5         Assert.hasText(beanName, "Bean name must not be empty");
     6         Assert.notNull(beanDefinition, "BeanDefinition must not be null");
     7 
     8         if (beanDefinition instanceof AbstractBeanDefinition) {
     9             try {
    10                 ((AbstractBeanDefinition) beanDefinition).validate();
    11             }
    12             catch (BeanDefinitionValidationException ex) {
    13                 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
    14                         "Validation of bean definition failed", ex);
    15             }
    16         }
    17 
    18         BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
    19         if (existingDefinition != null) {
    20             if (!isAllowBeanDefinitionOverriding()) {
    21                 throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
    22             }
    23             else if (existingDefinition.getRole() < beanDefinition.getRole()) {
    24                 // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
    25                 if (logger.isInfoEnabled()) {
    26                     logger.info("Overriding user-defined bean definition for bean '" + beanName +
    27                             "' with a framework-generated bean definition: replacing [" +
    28                             existingDefinition + "] with [" + beanDefinition + "]");
    29                 }
    30             }
    31             else if (!beanDefinition.equals(existingDefinition)) {
    32                 if (logger.isDebugEnabled()) {
    33                     logger.debug("Overriding bean definition for bean '" + beanName +
    34                             "' with a different definition: replacing [" + existingDefinition +
    35                             "] with [" + beanDefinition + "]");
    36                 }
    37             }
    38             else {
    39                 if (logger.isTraceEnabled()) {
    40                     logger.trace("Overriding bean definition for bean '" + beanName +
    41                             "' with an equivalent definition: replacing [" + existingDefinition +
    42                             "] with [" + beanDefinition + "]");
    43                 }
    44             }
    45             this.beanDefinitionMap.put(beanName, beanDefinition);
    46         }
    47         else {
    48             if (hasBeanCreationStarted()) {
    49                 // Cannot modify startup-time collection elements anymore (for stable iteration)
    50                 synchronized (this.beanDefinitionMap) {
    51                     this.beanDefinitionMap.put(beanName, beanDefinition);
    52                     List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
    53                     updatedDefinitions.addAll(this.beanDefinitionNames);
    54                     updatedDefinitions.add(beanName);
    55                     this.beanDefinitionNames = updatedDefinitions;
    56                     if (this.manualSingletonNames.contains(beanName)) {
    57                         Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
    58                         updatedSingletons.remove(beanName);
    59                         this.manualSingletonNames = updatedSingletons;
    60                     }
    61                 }
    62             }
    63             else {
    64                 // Still in startup registration phase
    65                 this.beanDefinitionMap.put(beanName, beanDefinition);
    66                 this.beanDefinitionNames.add(beanName);
    67                 this.manualSingletonNames.remove(beanName);
    68             }
    69             this.frozenBeanDefinitionNames = null;
    70         }
    71 
    72         if (existingDefinition != null || containsSingleton(beanName)) {
    73             resetBeanDefinition(beanName);
    74         }
    75     }

      到这里,bean注册完成了,然后调用refresh()方法进行实例化。

     1 @Override
     2     public void refresh() throws BeansException, IllegalStateException {
     3         synchronized (this.startupShutdownMonitor) {
     4             // Prepare this context for refreshing.
     5             // 准备工作,包括设置启动时间,是否激活标识位,
     6             // 初始化属性源(property source)设置
     7             prepareRefresh();
     8 
     9             // Tell the subclass to refresh the internal bean factory.
    10             // 通过子类来获取之前注册了bean的容器工厂beanFactory
    11             // 这里我们是获得DefaultListableBeanFactory这个工厂类
    12             ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    13 
    14             // Prepare the bean factory for use in this context.
    15             prepareBeanFactory(beanFactory);
    16 
    17             try {
    18                 // Allows post-processing of the bean factory in context subclasses.
    19                 postProcessBeanFactory(beanFactory);
    20 
    21                 // Invoke factory processors registered as beans in the context.
    22                 invokeBeanFactoryPostProcessors(beanFactory);
    23 
    24                 // Register bean processors that intercept bean creation.
    25                 registerBeanPostProcessors(beanFactory);
    26 
    27                 // Initialize message source for this context.
    28                 initMessageSource();
    29 
    30                 // Initialize event multicaster for this context.
    31                 initApplicationEventMulticaster();
    32 
    33                 // Initialize other special beans in specific context subclasses.
    34                 onRefresh();
    35 
    36                 // Check for listener beans and register them.
    37                 registerListeners();
    38 
    39                 // Instantiate all remaining (non-lazy-init) singletons.
    40                 finishBeanFactoryInitialization(beanFactory);
    41 
    42                 // Last step: publish corresponding event.
    43                 finishRefresh();
    44             }
    45 
    46             catch (BeansException ex) {
    47                 if (logger.isWarnEnabled()) {
    48                     logger.warn("Exception encountered during context initialization - " +
    49                             "cancelling refresh attempt: " + ex);
    50                 }
    51 
    52                 // Destroy already created singletons to avoid dangling resources.
    53                 destroyBeans();
    54 
    55                 // Reset 'active' flag.
    56                 cancelRefresh(ex);
    57 
    58                 // Propagate exception to caller.
    59                 throw ex;
    60             }
    61 
    62             finally {
    63                 // Reset common introspection caches in Spring's core, since we
    64                 // might not ever need metadata for singleton beans anymore...
    65                 resetCommonCaches();
    66             }
    67         }
    68     }
  • 相关阅读:
    Codeforces Round #131 (Div. 2) E. Relay Race dp
    Codeforces Round #130 (Div. 2) C
    Codeforces Round #130 (Div. 2) A. Dubstep
    UVA 11858 Frosh Week 逆序对统计
    UVA 11149 Power of Matrix 快速幂
    UVA 12382 Grid of Lamps 贪心
    POJ 3614 Sunscreen 贪心
    Codeforces Round #238 (Div. 2) D. Toy Sum 暴搜
    Codeforces Round #227 (Div. 2) E. George and Cards 线段树+set
    Codeforces Round #327 (Div. 2) E. Three States
  • 原文地址:https://www.cnblogs.com/wk-missQ1/p/12443177.html
Copyright © 2011-2022 走看看