Spring原理(1)——容器

打印 上一主题 下一主题

主题 1030|帖子 1030|积分 3090

容器接口


BeanFactory


  • 是ApplicationContext的父接口,所有ApplicationContext的实现都组合了BeanFactory。
  • BeanFactory才是Spring的核心容器。

从BeanFactory提供的方法来看,主要是从容器中获取Bean。实际上控制反转,依赖注入以及Bean的生命周期管理,都由它的实现类提供。如下展示了BeanFactory其中一个实现类DefaultListableBeanFactory的继承关系。

可以看到,它的继承路线上有一个DefaultSingletonBeanRegistry类,这个类我们打开可以看到如下代码段,其中singletonObjects对象正是容器中所有单例对象被保存的地方。
  1. public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
  2.         /** Cache of singleton objects: bean name to bean instance. */
  3.         private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);  // 保存了所有的单例对象
  4.         /** Cache of singleton factories: bean name to ObjectFactory. */
  5.         private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
  6.        
  7.         ...
  8. }
复制代码
通常我们会使用如下方式来启动和加载Spring容器
  1. @SpringBootApplication
  2. public class SsmpApplication {
  3.     public static void main(String[] args) throws IOException {
  4.         final ConfigurableApplicationContext context = SpringApplication.run(SsmpApplication.class, args);
  5.         // MessageSource接口提供的功能,实现国际化能力
  6.         context.getMessage("hi", null, Locale.CHINA);
  7.         context.getMessage("hi", null, Locale.US);
  8.         // ResourcePatternResolver接口提供的能力,实现读取资源文件的能力
  9.         final Resource[] resources = context.getResources("classpath*:spring.factories");
  10.         // EnvironmentCapable接口提供的能力,实现获取环境参数的能力,可以获取环境变量、配置等
  11.         final String java_home = context.getEnvironment().getProperty("java_home");
  12.         final String port = context.getEnvironment().getProperty("server.port");
  13.         // ApplicationEventPublisher提供的能力,可以发送事件,实现解耦
  14.         context.publishEvent(new MyEvent(context));
  15.     }
  16.     public static class MyEvent extends ApplicationEvent {
  17.         public MyEvent(Object source) {
  18. package com.leo.domain;
  19. import lombok.Data;
  20. @Data
  21. public class Book {
  22.     private Integer id;
  23.     private String type;
  24.     private String name;
  25.     private String description;
  26. }super(source);
  27.         }
  28.     }
  29. }
复制代码
其内部实现如果简单的拆开来,可以用如下步骤表示,BeanFactory是真正的容器,我们使用XmlBeanDefinitionReader将xml中定义的bean转化成BeanDefinition并注册到BeanFactory中。
  1. package com.leo.ssmp;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.beans.factory.config.BeanDefinition;
  5. import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
  6. import org.springframework.beans.factory.config.BeanPostProcessor;
  7. import org.springframework.beans.factory.support.BeanDefinitionBuilder;
  8. import org.springframework.beans.factory.support.DefaultListableBeanFactory;
  9. import org.springframework.boot.autoconfigure.SpringBootApplication;
  10. import org.springframework.context.annotation.AnnotationConfigUtils;
  11. import org.springframework.context.annotation.Bean;
  12. import org.springframework.context.annotation.Configuration;
  13. import java.util.Collection;
  14. @SpringBootApplication
  15. @Slf4j
  16. public class SsmpApplication {
  17.     public static void main(String[] args) {
  18.         // 将MyConfig类注册到BeanFactory中,由BeanFactory管理Bean的生成,销毁
  19.         DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
  20.         final BeanDefinition configDefinition = BeanDefinitionBuilder.genericBeanDefinition(MyConfig.class)
  21. package com.leo.domain;
  22. import lombok.Data;
  23. @Data
  24. public class Book {
  25.     private Integer id;
  26.     private String type;
  27.     private String name;
  28.     private String description;
  29. }.setScope("singleton")
  30. package com.leo.domain;
  31. import lombok.Data;
  32. @Data
  33. public class Book {
  34.     private Integer id;
  35.     private String type;
  36.     private String name;
  37.     private String description;
  38. }.getBeanDefinition();
  39.         beanFactory.registerBeanDefinition("config", configDefinition);
  40.         // 向BeanFactory上注册一些后处理器,这些后处理器可以解析@Configuration和@Bean这些注解
  41.         AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
  42.         // BeanFactory后处理器,执行后处理操作,处理@Configuration注解,将bean1和bean2生成出来
  43.         final Collection<BeanFactoryPostProcessor> beanFactoryPostProcessors = beanFactory.getBeansOfType(
  44. package com.leo.domain;
  45. import lombok.Data;
  46. @Data
  47. public class Book {
  48.     private Integer id;
  49.     private String type;
  50.     private String name;
  51.     private String description;
  52. }BeanFactoryPostProcessor.class).values();
  53.         log.info("---------------BeanFactory后处理器------------------");
  54.         beanFactoryPostProcessors.forEach(beanFactoryPostProcessor -> log.info(beanFactoryPostProcessor.toString()));
  55.         beanFactoryPostProcessors.forEach(beanFactoryPostProcessor -> {
  56. package com.leo.domain;
  57. import lombok.Data;
  58. @Data
  59. public class Book {
  60.     private Integer id;
  61.     private String type;
  62.     private String name;
  63.     private String description;
  64. }beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
  65.         });
  66.         log.info("---------------BeanFactory后处理器------------------");
  67.         // Bean后处理器,针对Bean的生命周期的各个阶段做扩展,例如@Autowired @Resource,
  68.         // 这样才能在生成bean1后,向bean1中注入bean2
  69.         final Collection<BeanPostProcessor> beanPostProcessors = beanFactory.getBeansOfType(BeanPostProcessor.class)
  70. package com.leo.domain;
  71. import lombok.Data;
  72. @Data
  73. public class Book {
  74.     private Integer id;
  75.     private String type;
  76.     private String name;
  77.     private String description;
  78. }.values();
  79.         log.info("----------------Bean后处理器-----------------");
  80.         beanPostProcessors.forEach(beanPostProcessor -> log.info(beanPostProcessor.toString()));
  81.         beanPostProcessors.forEach(beanFactory::addBeanPostProcessor);
  82.         log.info("----------------Bean后处理器-----------------");
  83.         log.info("------------------注册的所有Bean定义信息------------------");
  84.         final String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
  85.         for (String beanDefinitionName : beanDefinitionNames) {
  86. package com.leo.domain;
  87. import lombok.Data;
  88. @Data
  89. public class Book {
  90.     private Integer id;
  91.     private String type;
  92.     private String name;
  93.     private String description;
  94. }log.info(beanDefinitionName);
  95.         }
  96.         log.info("------------------注册的所有Bean定义信息------------------");
  97.         final Bean1 bean1 = beanFactory.getBean(Bean1.class);
  98.         log.info(bean1.getBean2().toString());
  99.     }
  100.     @Configuration
  101.     static class MyConfig {
  102.         @Bean
  103.         public Bean1 bean1() {
  104. package com.leo.domain;
  105. import lombok.Data;
  106. @Data
  107. public class Book {
  108.     private Integer id;
  109.     private String type;
  110.     private String name;
  111.     private String description;
  112. }return new Bean1();
  113.         }
  114.         @Bean
  115.         public Bean2 bean2() {
  116. package com.leo.domain;
  117. import lombok.Data;
  118. @Data
  119. public class Book {
  120.     private Integer id;
  121.     private String type;
  122.     private String name;
  123.     private String description;
  124. }return new Bean2();
  125.         }
  126.     }
  127.     static class Bean1 {
  128.         @Autowired
  129.         private Bean2 bean2;
  130.         public Bean1() {
  131. package com.leo.domain;
  132. import lombok.Data;
  133. @Data
  134. public class Book {
  135.     private Integer id;
  136.     private String type;
  137.     private String name;
  138.     private String description;
  139. }log.info("Bean1 construct...");
  140.         }
  141.         public Bean2 getBean2() {
  142. package com.leo.domain;
  143. import lombok.Data;
  144. @Data
  145. public class Book {
  146.     private Integer id;
  147.     private String type;
  148.     private String name;
  149.     private String description;
  150. }return bean2;
  151.         }
  152.     }
  153.     static class Bean2 {
  154.         public Bean2() {
  155. package com.leo.domain;
  156. import lombok.Data;
  157. @Data
  158. public class Book {
  159.     private Integer id;
  160.     private String type;
  161.     private String name;
  162.     private String description;
  163. }log.info("Bean2 construct");
  164.         }
  165.     }
  166. }
复制代码
以上代码的运行结果如下:
  1. 10:56:43.379 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
  2. 10:56:43.395 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
  3. 10:56:43.398 [main] INFO com.leo.ssmp.SsmpApplication - ---------------BeanFactory后处理器------------------
  4. 10:56:43.398 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.annotation.ConfigurationClassPostProcessor@724af044
  5. 10:56:43.398 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.event.EventListenerMethodProcessor@4678c730
  6. 10:56:43.512 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
  7. 10:56:43.513 [main] INFO com.leo.ssmp.SsmpApplication - ---------------BeanFactory后处理器------------------
  8. 10:56:43.513 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
  9. 10:56:43.513 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
  10. 10:56:43.516 [main] INFO com.leo.ssmp.SsmpApplication - ----------------Bean后处理器-----------------
  11. 10:56:43.516 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@6385cb26
  12. 10:56:43.516 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@38364841
  13. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - ----------------Bean后处理器-----------------
  14. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - ------------------注册的所有Bean定义信息------------------
  15. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - config
  16. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.annotation.internalConfigurationAnnotationProcessor
  17. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.annotation.internalAutowiredAnnotationProcessor
  18. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.annotation.internalCommonAnnotationProcessor
  19. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.event.internalEventListenerProcessor
  20. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.event.internalEventListenerFactory
  21. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - bean1
  22. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - bean2
  23. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - ------------------注册的所有Bean定义信息------------------
  24. 10:56:43.517 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean1'
  25. 10:56:43.518 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'config'
  26. 10:56:43.529 [main] INFO com.leo.ssmp.SsmpApplication - Bean1 construct...
  27. 10:56:43.535 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean2'
  28. 10:56:43.536 [main] INFO com.leo.ssmp.SsmpApplication - Bean2 construct
  29. 10:56:43.537 [main] INFO com.leo.ssmp.SsmpApplication - com.leo.ssmp.SsmpApplication$Bean2@55040f2f
  30. Process finished with exit code 0
复制代码
我们会发现这是容器里只有一个Bean,但是当我们用springboot自动配置来启动容器时,会发现即使我们不定义Bean,默认也会加载一些内置的bean。那么Spring是如何加载这些内置的Bean的呢。我们可以在xml文件中加入如下配置:
  1. package com.leo.domain;
  2. import lombok.Data;
  3. @Data
  4. public class Book {
  5.     private Integer id;
  6.     private String type;
  7.     private String name;
  8.     private String description;
  9. }
复制代码
这样我们运行上面的代码时打印出来的结果如下:
  1. 10:56:43.379 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
  2. 10:56:43.395 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
  3. 10:56:43.398 [main] INFO com.leo.ssmp.SsmpApplication - ---------------BeanFactory后处理器------------------
  4. 10:56:43.398 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.annotation.ConfigurationClassPostProcessor@724af044
  5. 10:56:43.398 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.event.EventListenerMethodProcessor@4678c730
  6. 10:56:43.512 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
  7. 10:56:43.513 [main] INFO com.leo.ssmp.SsmpApplication - ---------------BeanFactory后处理器------------------
  8. 10:56:43.513 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
  9. 10:56:43.513 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
  10. 10:56:43.516 [main] INFO com.leo.ssmp.SsmpApplication - ----------------Bean后处理器-----------------
  11. 10:56:43.516 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@6385cb26
  12. 10:56:43.516 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@38364841
  13. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - ----------------Bean后处理器-----------------
  14. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - ------------------注册的所有Bean定义信息------------------
  15. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - config
  16. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.annotation.internalConfigurationAnnotationProcessor
  17. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.annotation.internalAutowiredAnnotationProcessor
  18. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.annotation.internalCommonAnnotationProcessor
  19. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.event.internalEventListenerProcessor
  20. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.event.internalEventListenerFactory
  21. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - bean1
  22. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - bean2
  23. 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - ------------------注册的所有Bean定义信息------------------
  24. 10:56:43.517 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean1'
  25. 10:56:43.518 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'config'
  26. 10:56:43.529 [main] INFO com.leo.ssmp.SsmpApplication - Bean1 construct...
  27. 10:56:43.535 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean2'
  28. 10:56:43.536 [main] INFO com.leo.ssmp.SsmpApplication - Bean2 construct
  29. 10:56:43.537 [main] INFO com.leo.ssmp.SsmpApplication - com.leo.ssmp.SsmpApplication$Bean2@55040f2f
  30. Process finished with exit code 0org.springframework.context.annotation.internalConfigurationAnnotationProcessororg.springframework.context.annotation.internalAutowiredAnnotationProcessororg.springframework.context.annotation.internalCommonAnnotationProcessororg.springframework.context.event.internalEventListenerProcessororg.springframework.context.event.internalEventListenerFactory
复制代码
可以看到这时已经加载了很多处理注解和事件监听的Bean。
FileSystemXmlApplicationContext

基本原理与ClassPathXmlApplicationContext相似,只不过这里改为从文件系统直接读取xml配置。
AnnotationConfigApplicationContext

直接通过@Configuration注解的类来加载Bean,这种方法加载Bean时,会默认加载注解处理器这些内置的Bean。同时还会将config类也加载为Bean。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

南飓风

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表