何亦冷

导航

Spring的IOC容器, AOP切面及启动流程简述

## IOC容器
1. 往容器中添加Bean的四种方式
    * @Component (@Controller, @Service, @Repository): 适用于自己写的类
    * @Bean (@Configuration里面): 可以添加三方组件(因为第三方组件是别人写的, 无法在其文件中写@Component)
    * @Import : 快速导入组件
        - 普通: 简化三方组件的简单导入(比如很多@Bean只需要简单new一下, 使用此注解就减少了代码量)
        - 扩展1: ImportSelector#selectImports, 返回需要导入的全类名字符串数组
        - 扩展2: ImportBeanDefinitionRegistrar#registerBeanDefinitions, 手动在BeanDefinition级别向容器中注册组件
        - 备注: Spring的@EnableXXX功能都是使用此注解向容器中添加YYY组件实现的, 比如@EnableAsync, @EnableScheduling, @EnableAspectJAutoProxy等等
    * FactoryBean: 工厂Bean, getObject方法的返回值导入组件. 
        - 适用于创建Bean是一个非常复杂代码量很多的场景, 比如ProxyFactoryBean, SqlSessionFactoryBean

2. 组件扫描与定制化
    * 扫描: @Configuration上标注的@ComponentScan
        - 指定基础包, 可以自定义包含或排除的过滤器, 过滤器类型: 注解, 指定类型, 自定义等
    * 定制化
        - @Scope: 是否单实例的. 默认为单实例, 容器启动就创建对象, 可以加入@Lazy设置为延迟加载; 设置为多实例后变为懒汉模式加载
        - @Conditional: 条件满足时才加入容器
        - @Profile: 环境满足时才加入容器
    * 属性赋值
        - @PropertySource: 指定property文件
        - @Value: 支持Spel表达式
    * 自动装配
        - @Autowired: 先按照类型装配, 多个时再按照属性名称装配
            * @Primary: 优先装配的组件
            * @Qualifier: 指定特定组件状态
            * JSR250的@Resource, JSR330的@Inject, 功能类似却不如@Autowired完善, 建议@Autowired
    * 使用底层组件: 实现xxxAware接口

3. 组件的生命周期
    * 单实例bean容器启动创建, 容器销毁调用销毁方法; 多实例bean启动不创建, 且销毁IOC容器不管理
    * 初始化和销毁方法
        - @Bean的initMethod, destroyMethod指定
        - Bean实现InitializingBean, DisposableBean接口
        - JSR250规范: @PostConstruct, @ProDestory注解
    * 后置处理器: BeanPostProcessor, 拦截所有bean的创建过程, 在init方法前后执行

## AOP切面
1. 开启: @EnableAspectJAutoProxy
2. 使用: 编写一个切面(@Aspect), 并将其放入容器中(@Component)即可
    * 切点: @Pointcut
    * 通知: 前置/后置/异常/最终/环绕

## 启动流程
```
    AnnotationConfigApplicationContext appContext = new AnnotationConfigApplicationContext(MainConfig.class);

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    this();                      // 初始化beanFactory工程, reader 读取器, scanner 扫描器
            this.beanFactory = new DefaultListableBeanFactory();      // 初始化bean工厂(父类的空参数构造方法中), new这个是因为功能最多(可以查看类继承结构)
            this.reader = new AnnotatedBeanDefinitionReader(this);    // 注解bean定义读取器: 创建标准环境(系统属性/系统环境变量), 表达式评估器conditionEvaluator
                                                                      //    向容器中注册注解配置处理器: ConfigurationClassPostProcessor, AutowiredAnnotationBeanPostProcessor等
            this.scanner = new ClassPathBeanDefinitionScanner(this);  // 类路径bean定义扫描器: 标记@Component注解是扫描时需要加入容器的过滤器
    register(componentClasses);  // 向容器中注册主配置类
    refresh();                   // 容器刷新(12步骤)

    //~~~~~~~~~~~~~~~~~~~~~~~~~~refresh()~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.                    ==> 1.准备刷新: 记录时间, 设置状态, 初始化属性源(空方法), 验证必需属性
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory. ==> 2.刷新bean工厂: 仅设置个状态, 如果是RefreshableApplicationContext则会销毁单实例bean,重新创建
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 

            // Prepare the bean factory for use in this context.       ==> 3.设置spel表达式解析器,资源编辑注册器,xxxAware后置处理器,监听探测器,向容器中注册环境/系统属性/系统环境
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses. ==> 4.空方法
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.     ==> 5.**bean工厂后置处理器执行: 解析配置类(@Configuration), 把所有的bean定义都加入到工厂中**
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.            ==> 6.注册bean后缀处理器, 用于拦截bean的创建
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.                       ==> 7.初始化消息源(策略模式解析消息,支持参数化和国际化)
                initMessageSource();

                // Initialize event multicaster for this context.                    ==> 8.初始化事件多播器
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.    ==> 9.空方法(留给子类实现, SpringBoot中在此处启动tomcat)
                onRefresh();

                // Check for listener beans and register them.                       ==> 10.注册监听器, 并发布早期事件
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.             ==> 11.**冻结配置, 并初始化所有的单实例bean**
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.                           ==> 12.完成刷新: 清理缓存, 初始化生命周期处理器并调用器onRefresh方法(eureka发现的启动在此处), 发布刷新完成事件
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }


```

 

posted on 2020-08-02 00:51  何亦冷  阅读(685)  评论(0编辑  收藏  举报