Java Config

是什么

java config是指基于java配置的spring。传统的Spring一般都是基本xml配置的,后来spring3.0新增了许多java config的注解,特别是spring boot,基本都是清一色的java config。

为什么

  • JavaConfig 使用纯Java代码的方式,可以充分利用复用、继承、多态等特性
  • 有更多的自由度来控制Bean的初始化,注入以及复杂对象的构建
  • 由于只用到Java,只需有IDE就可以尽情的掌控配置逻辑

怎么实现

Spring Java Config 示例代码

BeanFactory注册 Bean

  • org.springframework.context.annotation.AnnotationConfigApplicationContext

org.springframework.context.support.AbstractApplicationContext.refresh 方法

  1. public abstract class AbstractApplicationContext extends DefaultResourceLoader
  2. implements ConfigurableApplicationContext {
  3. // ...
  4. public void refresh() throws BeansException, IllegalStateException {
  5. synchronized (this.startupShutdownMonitor) {
  6. // Prepare this context for refreshing.
  7. // 准备刷新上下文环境
  8. prepareRefresh();
  9. // Tell the subclass to refresh the internal bean factory.
  10. // 初始化 BeanFactory, 并进行 XML 文件读取
  11. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  12. // Prepare the bean factory for use in this context.
  13. // 对BeanFactory 在当前上下文中进行功能填充
  14. prepareBeanFactory(beanFactory);
  15. try {
  16. // Allows post-processing of the bean factory in context subclasses.
  17. // 子类覆盖方法做额外处理
  18. postProcessBeanFactory(beanFactory);
  19. // Invoke factory processors registered as beans in the context.
  20. // 激活 N 多 BeanFactory 处理器
  21. invokeBeanFactoryPostProcessors(beanFactory);
  22. // Register bean processors that intercept bean creation.
  23. // 注册拦截Bean创建的Bean 处理器
  24. registerBeanPostProcessors(beanFactory);
  25. // Initialize message source for this context.
  26. // 国际化
  27. initMessageSource();
  28. // Initialize event multicaster for this context.
  29. // 初始化应用消息广播器
  30. initApplicationEventMulticaster();
  31. // Initialize other special beans in specific context subclasses.
  32. // 在特定上下文初始化其它特殊的Bean
  33. onRefresh();
  34. // Check for listener beans and register them.
  35. // 检查监听器Bean并且注册
  36. registerListeners();
  37. // Instantiate all remaining (non-lazy-init) singletons.
  38. // 实例化所有非延迟加载的实例
  39. finishBeanFactoryInitialization(beanFactory);
  40. // Last step: publish corresponding event.
  41. // 发布通信事件
  42. finishRefresh();
  43. }
  44. catch (BeansException ex) {
  45. if (logger.isWarnEnabled()) {
  46. logger.warn("Exception encountered during context initialization - " +
  47. "cancelling refresh attempt: " + ex);
  48. }
  49. // Destroy already created singletons to avoid dangling resources.
  50. destroyBeans();
  51. // Reset 'active' flag.
  52. cancelRefresh(ex);
  53. // Propagate exception to caller.
  54. throw ex;
  55. }
  56. finally {
  57. // Reset common introspection caches in Spring's core, since we
  58. // might not ever need metadata for singleton beans anymore...
  59. resetCommonCaches();
  60. }
  61. }
  62. }
  63. // ...
  64. }
  • org.springframework.context.annotation.ConfigurationClassPostProcessor

    • Spring 容器初始化时注册 ConfigurationClassPostProcessor
    • Spring 容器初始化执行 refresh() 方法中调用 ConfigurationClassPostProcessor
    • ConfigurationClassPostProcessor 处理器借助 ConfigurationClassParser 完成配置类解析
    • ConfigurationClassParser 配置内解析过程中完成嵌套的 MemberClass@PropertySource 注解、@ComponentScan 注解(扫描package 下的所有Class 并进行迭代解析,
      主要是 @Component组件解析及注册)、@ImportResource@Bean 等处理
    • 完成 @Bean 注册,@ImportResource 指定 bean 的注册以及 @Import 的 bean 注册
    • @Bean注解的方法在解析的时候作为ConfigurationClass的一个属性,最后还是会转换成BeanDefinition进行处理, 而实例化的时候会作为一个工厂方法进行Bean的创建