• 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();
                }
            }
        }
    
    
    ```
  • 相关阅读:
    iOS中Block介绍(一)基础
    iOS消息推送机制的实现
    iOS AvPlayer AvAudioPlayer音频的后台播放问题
    git 解决fatal: Not a git repository
    执行git命令出现 xcrun: error:
    ios UIView的clipsTobounds属性
    UIWindow的层级问题Level
    解决方案:The file * couldn't be opened because you don't have permission to view it
    NSString 中包含中文字符时转换为NSURL
    UIView动画
  • 原文地址:https://www.cnblogs.com/hepengju/p/13417456.html
Copyright © 2020-2023  润新知