spring系列学习记录-YL2020.05

下列spring系列参考【路人甲Java】的spring系列,每个系列的标题我都标注了原路径跳转,尊重原创,也感谢原创分享。可以通过标题点进去看更多的详细案例。 1-14个人觉得可以快速简单看看,15开始跟着代码案例多玩玩。

Spring系列第1篇:为何要学spring?
    简化项目开发,让我们的项目更容易维护和扩展

Spring系列第2篇:控制反转(IoC)与依赖注入(DI)
    1.IOC控制反转,是一种设计理念,将对象创建和组装的主动控制权利交给了spring容器去做,控制的动作被反转了,降低了系统的耦合度,利于系统维护和扩展,主要就是指需要使用的对象的组装控制权被反转了,之前是自己要做的,现在交给spring容器做了。
    2.DI依赖注入,表示spring容器中创建对象时给其设置依赖对象的方式,通过某些注入方式可以让系统更灵活,比如自动注入等可以让系统变的很灵活,这个后面的文章会细说。
    3.spring容器:主要负责容器中对象的创建、组装、对象查找、对象生命周期的管理等等操作。

Spring系列第3篇:Spring容器基本使用及原理
    1.IOC容器是具有依赖注入功能的容器,负责对象的实例化、对象的初始化,对象和对象之间依赖关系配置、对象的销毁、对外提供对象的查找等操作,对象的整个生命周期都是由容器来控制。我们需要使用的对象都由ioc容器进行管理,不需要我们再去手动通过new的方式去创建对象,由ioc容器直接帮我们组装好,当我们需要使用的时候直接从ioc容器中直接获取就可以了。
    2.那么spring ioc容器是如何知道需要管理哪些对象呢?
        需要我们给ioc容器提供一个配置清单,这个配置支持xml格式和java注解的方式,在配置文件中列出需要让ioc容器管理的对象,以及可以指定让ioc容器如何构建这些对象,当spring容器启动的时候,就会去加载这个配置文件,然后将这些对象给组装好以供外部访问者使用。
    3.这里所说的IOC容器也叫spring容器。
    4.spring容器对象
      spring内部提供了很多spring容器的接口和对象,常见几个容器接口+Impl
        1.BeanFactory接口 它是spring容器的顶层接口,提供容器最基本的功能。
        2.ApplicationContext接口 extends BeanFactory接口
            AOP + 国际化 + 事件支持等等
        3.ClassPathXmlApplicationContext类 implements ApplicationContext接口
        4.AnnotationConfigApplicationContext类 implements ApplicationContext接口

Spring系列第4篇:xml中bean定义详解(-)
    被spring管理的对象统称为bean,通过bean xml配置文件告诉spring容器需要管理哪些bean;我们需要给bean定义一个名称,spring内部将这些名称和具体的bean对象进行绑定,然后spring容器可以通过这个的名称找对我们需要的对象,这个名称叫做bean的名称,在一个spring容器中需要是唯一的。

Spring系列第5篇:创建bean实例这些方式你们都知道?
    1.通过反射调用构造方法创建bean对象
        <bean id="" class=""/>    无参构造
        <bean id="" class="">    有参构造
            <constructor-arg index="0" value="" ref="">
    2.通过静态工厂方法创建bean对象
        <bean id="" class="" factory-method=""/>    静态工厂无参
        <bean id="" class="" factory-method=""/>    实例工厂有参
            <constructor-arg index="0" value=""/>
    3.通过实例工厂方法创建bean对象
        <bean id="aA" class="..."/>
        <bean id="" factory-bean="aA" factory-method="">    实例无参
        <bean id="" factory-bean="aA" factory-method="">    实例有参
            <constructor-arg index="" value="" ref=""/>
    4.通过FactoryBean创建bean对象
        <bean id="" class="实现了FactoryBean接口的类,需要自己编写">
    5.前三种方式最根本的区别还是创建方式的不同。
    第一种,通过默认的无参构造方式创建,其本质就是把类交给Spring自带的工厂(BeanFactory)管理、由Spring自带的工厂模式帮我们维护和创建这个类。
        如果是有参的构造方法,也可以通过XML配置传入相应的初始化参数,这种也是开发中用的最多的。
    第二种,通过静态工厂创建,其本质就是把类交给我们自己的静态工厂管理,Spring只是帮我们调用了静态工厂创建实例的方法,
        而创建实例的这个过程是由我们自己的静态工厂实现的,在实际开发的过程中,很多时候我们需要使用到第三方jar包提供给我们的类,
        而这个类没有构造方法,而是通过第三方包提供的静态工厂创建的,这是时候,如果我们想把第三方jar里面的这个类交由spring来管理的话,
        就可以使用Spring提供的静态工厂创建实例的配置。
    第三种,通过实例工厂创建,其本质就是把创建实例的工厂类交由Spring管理,同时把调用工厂类的方法创建实例的这个过程也交由Spring管理,
        看创建实例的这个过程也是有我们自己配置的实例工厂内部实现的。在实际开发的过程中,如Spring整合Hibernate就是通过这种方式实现的。
        但对于没有与Spring整合过的工厂类,我们一般都是自己用代码来管理的。

Spring系列第6篇:玩转bean scope,避免跳坑里!
    bean的作用域:
        1.自带两种:singleton(默认单列,需要考虑线程安全问题)和 prototype(多例,考虑性能问题)
        2.还有三种,是spring Web容器环境中才支持的request、session、application
        3.也可以自定义scope,实现Scope接口

Spring系列第7篇:依赖注入之手动注入
    1.spring依赖注入的方式:自动注入 + 手动注入(构造函数的方式、set属性的方式)
    <!-- 通过构造器方式注入容器中的bean,还可以分为三种:根据构造器参数索引注入、根据构造器参数类型注入、根据构造器参数名称注入 -->
        <constructor-arg index="0" ref="user"/>
    <!-- 通过setter方式注入容器中的bean -->
        <property name="userModel" ref="user"/>

    2.自动注入分为:
        byteName:按照名称进行注入
        byType:按类型进行注入
        constructor:按照构造方法进行注入
        default:默认注入方式,按名称
    
    3.创建bean四种方式 和 依赖注入方式 是两个概念( IOC 和 DI )
        Q1:有参构造和构造器注入如何区分???    A1:构造器注入,分为无参和有参。

 

Spring系列第8篇:自动注入(autowire)详解
    解决手动注入的不足:
        1.注入的对象比较多时配置文件代码量暴增 
        2.新增或者删除了一些依赖,还需要手动去调整bean xml中的依赖配置信息,否则会报错,不利于维护和扩展

Spring系列第9篇:depend-on到底是干什么的?
    spring不同bean的创建销毁顺序,通过depend-on干预bean创建和销毁顺序
    <bean id="bean1" class="" depend-on="bean2,bean3; bean4" />
    无依赖的bean创建顺序和定义的顺序一致,销毁顺序刚好相反
    通过构造器强依赖的bean,会先创建构造器参数中对应的bean,然后才会创建当前bean,销毁顺序刚好相反
    depend-on可以指定档期bean依赖的bean,通过这个可以确保depend-on指定的bean在当前bean创建之前先创建好,销毁顺序刚好相反

Spring系列第10篇:primary可以解决什么问题?
    当从容器中查找一个bean的时候,如果容器中出现多个Bean候选者时,可以通过primary="true"将当前bean置为首选者,
    那么查找的时候就会返回主要的候选者,否则将抛出异常。

Spring系列第11篇:bean中的autowire-candidate又是干什么的?
    autowire-candidate:设置当前bean在被其他对象作为自动注入对象的时候,是否作为候选bean,默认值是true。

Spring系列第12篇:lazy-init:bean延迟初始化
    spring bean初始化的方式2种方式:实时初始化 + 延时初始化 lazy-init="true"

Spring系列第13篇:使用继承简化bean配置(abstract & parent)
    1.bean元素的abstract属性为true的时候可以定义某个bean为一个抽象的bean,相当于定义了一个bean模板,spring容器并不会创建这个bean,从容器中查找abstract为true的bean的时候,会报错BeanIsAbstractException异常
    2.bean元素的parent属性可以指定当前bean的父bean,子bean可以继承父bean中配置信息,也可以自定义配置信息,这样可以覆盖父bean中的配置

Spring系列第14篇:lookup-method和replaced-method比较陌生,怎么玩的?
    spring中 单例bean中使用多例bean三种方式:
    1.implements ApplicationContextAware
    2.lookup-method:方法查找,可以对指定的bean的方法进行拦截,然后从容器中查找指定的bean作为被拦截方法的返回值
        <bean id="serviceA" class="com.javacode2018.lesson001.demo13.lookupmethod.ServiceA" scope="prototype"/>
        <bean id="serviceB" class="com.javacode2018.lesson001.demo13.lookupmethod.ServiceB">
            <lookup-method name="getServiceA" bean="serviceA"/>
        </bean>
    3.replaced-method:方法替换,可以实现bean方法替换的效果,整体来说比lookup-method更灵活一些
        <bean id="serviceA" class="com.javacode2018.lesson001.demo14.ServiceA" scope="prototype"/>
        <bean id="serviceB" class="com.javacode2018.lesson001.demo14.ServiceB">
            <replaced-method name="getServiceA" replacer="serviceBMethodReplacer"/>
        </bean>

Spring系列第15篇(Java动态代理&cglib代理)
        JDK:InvocationHandler-invoke        CGLIB:MethodInterceptor-intercept
  1.proxy使用注意
     jdk中的Proxy只能为接口生成代理类,如果你想给某个类创建代理类,那么Proxy是无能为力的,此时需要我们用到下面要说的cglib了。
    Proxy类中提供的几个常用的静态方法大家需要掌握
    通过Proxy创建代理对象,当调用代理对象任意方法时候,会被InvocationHandler接口中的invoke方法进行处理,这个接口内容是关键
  2.CGLIB和Java动态代理的区别
    Java动态代理只能够对接口进行代理,不能对普通的类进行代理(因为所有生成的代理类的父类为Proxy,Java类继承机制不允许多重继承);CGLIB能够代理普通类;
    Java动态代理使用Java原生的反射API进行操作,在生成类上比较高效;CGLIB使用ASM框架直接对字节码进行操作,在类的执行过程中比较高效

Spring系列第16篇:深入理解java注解及spring对注解的增强(预备知识)
    1.注解是干什么的? 
        1.注释给人看的,注解给机器看的
        2.注解是对代码的一种增强,可以在代码编译或者程序运行期间获取注解的信息,然后根据这些信息做各种牛逼的事情。
    2.一个注解可以使用多次么?如何使用?
        1.默认情况下注解是不允许重复使用的。
        2.如果我们想重复使用注解的时候,需要用到@Repeatable注解
    3.@Inherited是做什么的?
        @Inherit:实现类之间的注解继承,但是要注意:类可以继承父类上被@Inherited修饰的注解,而不能继承接口上被@Inherited修饰的注解
    4.@Target中的`TYPE_PARAMETER和TYPE_USER`用在什么地方?
        都是1.8以后的,类型参数上 TYPE_PARAMETER,跟泛型相关;     能用在任何类型名称上 TYPE_USE
    5.泛型中如何使用注解?
        TYPE_PARAMETER
    6.注解定义可以实现继承么?
        无法继承
    7.spring中对注解有哪些增强?@Aliasfor注解是干什么的?
        由于无法继承,就会存在 @A1{};  @A1 @B1{};  @B1 UseAnnotation13{}; 
        此时有个问题:此时如果想在UseAnnotation13上给B1上的A1注解设置值是没有办法的,注解定义无法继承导致的,如果注解定义上面能够继承,那用起来会爽很多,spring通过@Aliasfor方法解决了这个问题。

Spring系列第17篇:@Configration和@Bean注解详解(bean批量注册)
    1.spring中,类上加不加@Configuration注解,有什么区别?
        @Configuration注解修饰的类,会被spring通过cglib做增强处理,通过cglib会生成一个代理对象,代理会拦截所有被@Bean注解修饰的方法,可以确保一些bean是单例的
    2.不用@Configuration注解,能不能通过@Bean注解来注册bean?
        不管@Bean所在的类上是否有@Configuration注解,都可以将@Bean修饰的方法作为一个bean注册到spring容器中

Spring系列第18篇:@ComponentScan、@ComponentScans详解(bean批量注册)
    1.@ComponentScan注解是做什么的?
        @ComponentScan用于批量注册bean,spring会按照这个注解的配置,递归扫描指定包中的所有类,将满足条件的类批量注册到spring容器中
        一般在xml里面用<context:component-scan base-packing="xx.xx"/>
    2.basePackages的方式和basePackageClasses的方式有什么区别?你建议用哪个?为什么?
        可以通过value、basePackages、basePackageClasses 这几个参数来配置包的扫描范围
        指定包名的方式配置扫描范围存在隐患,包名被重命名之后,会导致扫描实现,所以一般我们在需要扫描的包中可以创建一个标记的接口或者类,作为basePackageClasses的值,通过这个来控制包的扫描范围
    3.useDefaultFilters有什么用?
        可以通过useDefaultFilters、includeFilters、excludeFilters这几个参数来配置类的过滤器,被过滤器处理之后剩下的类会被注册到容器中
    4.常见的过滤器有哪些类型?说说你知道的几个
        如上。
    5.@ComponentScan是在哪个类中处理的?说一下大概的解析过程?
        @ComponentScan注解会被ConfigurationClassPostProcessor类递归处理,最终得到所有需要注册的类。

Spring系列第19篇:@import详解(bean批量注册)
    1.@Import你用过么?是做什么的?
        1.先看Spring对它的注释,总结下来作用就是和xml配置的 <import />标签作用一样,允许通过它引入@Configuration标注的类 , 引入ImportSelector接口和ImportBeanDefinitionRegistrar接口的实现,也包括 @Component注解的普通类。
        2.总的来说:@Import可以用来批量导入需要注册的各种类,如普通的类、配置类,完成普通类和配置类中所有bean的注册。
    2.@Import使用有几种方式?有何区别?
        五/六种:
        1.value为普通的类
            @Import({Service1.class, Service2.class})
        2.value为@Configuration标注的类
        3.value为@CompontentScan标注的类
        4.value为ImportBeanDefinitionRegistrar接口类型,    这个接口提供了通过spring容器api的方式直接向容器中注册bean。
            4.1 定义ImportBeanDefinitionRegistrar接口实现类,在registerBeanDefinitions方法中使用registry来注册bean
            4.2 使用@Import来导入步骤1中定义的类
            4.3 使用步骤2中@Import标注的类作为AnnotationConfigApplicationContext构造参数创建spring容器
            4.4 使用AnnotationConfigApplicationContext操作bean
        5.value为ImportSelector接口类型
            5.1 定义ImportSelector接口实现类,在selectImports返回需要导入的类的名称数组
            5.2 使用@Import来导入步骤1中定义的类
            5.3 使用步骤2中@Import标注的类作为AnnotationConfigApplicationContext构造参数创建spring容器
            5.4 使用AnnotationConfigApplicationContext操作bean
        6.value为DeferredImportSelector接口类型
            见下面3
    3.DeferredImportSelector是做什么的?他和ImportSelector有什么区别?
        DeferredImportSelector是ImportSelector的子接口,既然是ImportSelector的子接口,所以也可以通过@Import进行导入,这个接口和ImportSelector不同地方有两点:
        1.延迟导入,我们可以在它导入的类中判断一下容器中是否已经注册了某个bean。后面还会看到@Conditional这个注解,这个注解可以按条件来注册bean,通过@Conditional来结合DeferredImportSelector可以做很多事情。
        2.指定导入的类的处理顺序
    4.可以介绍介绍一下spring中哪些功能是通过@Import来实现的?
        @Enablexxx
    5.可以介绍一下spring中是如何解析@Import注解的么?
        org.springframework.context.annotation.ConfigurationClassPostProcessor这个类处理的。
        @Configuration、@Bean、@CompontentScan、@CompontentScans都是被这个类处理的

Spring系列第20篇:@Conditional通过条件来控制bean的注册
    1.@Conditional是做什么的?
        @Conditional注解是从spring4.0才有的,可以用在任何类型或者方法上面。
        通过@Conditional注解可以配置一些条件判断,当所有条件都满足的时候,被@Conditional标注的目标才会被spring容器处理。
    2.@Conditional多个条件是什么逻辑关系?
        与
    3.条件判断在什么时候执行?
        1.配置类解析阶段:会得到一批配置类的信息,和一些需要注册的bean
        2.bean注册阶段:将配置类解析阶段得到的配置类和需要注册的bean注册到spring容器中
    4.ConfigurationCondition和Condition有什么区别?什么时候使用ConfigurationCondition?
        1.ConfigurationCondition使用的比较少,很多地方对这个基本上也不会去介绍,Condition接口基本上可以满足99%的需求了,但是springboot中却大量用到了ConfigurationCondition这个接口。
        2.区别:
            配置类的处理会依次经过2个阶段:配置类解析阶段和bean注册阶段,Condition接口类型的条件会对这两个阶段都有效,
            ConfigurationCondition让条件判断在bean注册阶段才起效。
        3.使用场景:
            判断bean存不存在的问题,通常会使用ConfigurationCondition这个接口,阶段为:REGISTER_BEAN,这样可以确保条件判断是在bean注册阶段执行的。
    5.多个Condition执行的顺序是什么样的?可以配置优先级么?
        1.默认情况下会按顺序执行。
        2.自定义的Condition可以实现PriorityOrdered接口或者继承Ordered接口,或者使用@Order注解,通过这些来指定这些Condition的优先级。
        排序规则:先按PriorityOrdered排序,然后按照order的值进行排序;也就是:PriorityOrdered asc,order值 asc
    6.可以介绍一下@Conditional常见的一些用法么?
        @Conditional注解是被下面这个类处理的: org.springframework.context.annotation.ConfigurationClassPostProcessor
    7.@Conditional使用的3步骤
        1.自定义一个类,实现Condition或ConfigurationCondition接口,实现matches方法,个人感觉这个是重点!!!
        2.在目标对象上使用@Conditional注解,并指定value的指为自定义的Condition类型
        3.启动spring容器加载资源,此时@Conditional就会起作用了
    8.总结:
        1.@Conditional注解可以标注在spring需要处理的对象上(配置类、@Bean方法),相当于加了个条件判断,通过判断的结果,让spring觉得是否要继续处理被这个注解标注的对象
        2.spring处理配置类大致有2个过程:解析配置类、注册bean,这两个过程中都可以使用@Conditional来进行控制spring是否需要处理这个过程
        3.Condition默认会对2个过程都有效
        4.ConfigurationCondition控制得更细一些,可以控制到具体那个阶段使用条件判断

Spring系列第21篇:注解实现依赖注入(@Autowired、@Resource、@Primary、@Qulifier)
    @Autowired - @Qualifier - required=true? 
                          | _ @Primary - required=true?
    @Autowired查找候选者可以简化为这样: 按类型找 -> 通过限定符@Qualifier过滤 -> @Primary -> @Priority -> 根据名称找(字段名称或者方法名称)
    概括为:先按类型找,然后按名称找

    1.通过注解的方式注入依赖对象,介绍一下你知道的几种方式
        @Autowired注解
        @Qualifier注解
        @Resource注解
        @Primary注解
        @Bean中注入的几种方式
    2.@Autowired和@Resource有何区别
        1.前者spring的,后者jdk的
        2.前者默认先按类型查找,后名称; 后者先按名称找,然后按类型找
    3.说一下@Autowired查找候选者的过程
    4.说一下@Resource查找候选者的过程
    5.@Qulifier有哪些用法?@Qulifier加在类上面是干什么用的?
        1.@Qualifier:限定符,可以在依赖注入查找候选者的过程中对候选者进行过滤。
        2.单独用在类上
        3.@Autowired结合@Qulifier指定注入的bean
        4.用在方法参数上
        5.用在setter方法上
    6.@Primary是做什么的?
        @Primary:设置为主要候选者
    7.泛型注入用过么?
    8.@Bean定义bean时注入依赖的几种方式
        硬编码方式
        @Autowired、@Resource的方式
        @Bean标注的方法参数的方式
    9.spring使用这个类处理@Autowired注解: org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor

Spring系列第22篇:@Scope、@DependsOn、@ImportResource、@Lazy 详解
    1.@Scope是做什么的?常见的用法有几种?
        @Scope:用来定义bean 的作用域;
        2种用法:第1种:标注在类上;第2种:和@Bean一起标注在方法上
    2.@DependsOn是做什么的?常见的用法有几种?
        @DependsOn:用来指定当前bean依赖的bean,可以确保在创建当前bean之前,先将依赖的bean创建好;
        2种用法:第1种:标注在类上;第2种:和@Bean一起标注在方法上
    3.@ImportResource干什么的?通常用在什么地方?
        @ImportResource:标注在配置类上,用来引入bean定义的配置文件
    4.@Lazy做什么的,通常用在哪些地方?常见的用法有几种?
        @Lazy:让bean延迟初始化;
        常见3种用法:第1种:标注在类上;第2种:标注在配置类上,会对配置类中所有的@Bean标注的方法有效;第3种:和@Bean一起标注在方法上

Spring系列第23篇:Bean生命周期详解
      阶段1:Bean元信息配置阶段
        1.Bean信息定义4种方式: API的方式、Xml文件方式、properties文件的方式、注解的方式
        2.Spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition对象结构。
        3.BeanDefinition接口:bean定义信息接口;BeanDefinition接口上面还继承了2个接口:
            AttributeAccessor接口:属性访问接口
                BeanDefinition继承这个接口,内部实际上是使用了LinkedHashMap来实现这个接口中的所有方法,通常我们通过这些方法来保存BeanDefinition定义过程中产生的一些附加信息。
            BeanMetadataElement:
                BeanDefinition继承这个接口,getSource返回BeanDefinition定义的来源
        4.总结:bean注册者只识别BeanDefinition对象,不管什么方式最后都会将这些bean定义的信息转换为BeanDefinition对象,然后注册到spring容器中。
      阶段2:Bean元信息解析阶段
          1.Bean元信息的解析就是将各种方式定义的bean配置信息解析为BeanDefinition对象。
        2.Bean元信息的解析主要有3种方式: 
            xml文件定义bean的解析,XML方式解析:XmlBeanDefinitionReader
            properties文件定义bean的解析,PropertiesBeanDefinitionReader
            注解方式定义bean的解析,AnnotatedBeanDefinitionReader
    阶段3:Spring Bean注册阶段
        1.bean注册阶段需要用到一个非常重要的接口:BeanDefinitionRegistry,它extends AliasRegistry(别名注册接口) 
        2.BeanDefinitionRegistry 的唯一实现:DefaultListableBeanFactory,
            大家可能看到有很多类也实现了BeanDefinitionRegistry接口,比如我们经常用到的AnnotationConfigApplicationContext,但实际上其内部是转发给了DefaultListableBeanFactory进行处理的,所以真正实现这个接口的类是DefaultListableBeanFactory。
    
    下面要介绍的从阶段4到阶段14,也就是从:BeanDefinition合并阶段到Bean初始化完成阶段,都是在调用getBean从容器中获取bean对象的过程中发送的操作,以下过程均来自于这个方法: org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

    阶段4:BeanDefinition合并阶段
        1.bean定义可能存在多级父子关系,合并的时候进进行递归合并,最终得到一个包含完整信息的RootBeanDefinition
        2.合并BeanDefinition会使用:org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition
        3.后面的阶段将使用合并产生的RootBeanDefinition。
    阶段5:Bean Class加载阶段
        1.这个阶段就是将bean的class名称转换为Class类型的对象。
        2.上面得到了Bean Class对象以及合并之后的BeanDefinition,下面就开始进入实例化这个对象的阶段了。
        3.Bean实例化分为3个阶段:前阶段、实例化阶段、后阶段;下面详解介绍。
    阶段6:Bean实例化阶段(2个小阶段)
        1.Bean实例化前阶段
            DefaultListableBeanFactory,这个类中有个非常非常重要的字段:
                private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
                BeanPostProcessor是一个接口,可以对bean的生命周期进行扩展。
        2.Bean实例化阶段
            SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors给开发者留个口子
    阶段7:合并后的BeanDefinition处理
        1.applyMergedBeanDefinitionPostProcessors{调用MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition}
        2.postProcessMergedBeanDefinition有2个实现类
            2.1 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
                在 postProcessMergedBeanDefinition 方法中对 @Autowired、@Value 标注的方法、字段进行缓存
            2.2 org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
                在 postProcessMergedBeanDefinition 方法中对 @Resource 标注的字段、@Resource 标注的方法、 @PostConstruct 标注的字段、 @PreDestroy标注的方法进行缓存
    阶段8:属性赋值阶段(3个小阶段)
        1.Bean实例化后阶段,会调用InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation这个方法,
            该方法返回false的时候,后续的Bean属性赋值前处理、Bean属性赋值都会被跳过了。
        2.Bean属性赋值前阶段,会调用InstantiationAwareBeanPostProcessor接口的postProcessProperties方法,
            该方法都返回空的时候,表示这个bean不需要设置属性,直接返回了,直接进入下一个阶段。
        3.Bean属性赋值阶段
            循环处理PropertyValues中的属性值信息,通过反射调用set方法将属性的值设置到bean实例中
            PropertyValues中的值是通过bean xml中property元素配置的,或者调用MutablePropertyValues中add方法设置的值。
    阶段9:Bean初始化阶段(5个小阶段)
        Bean Aware接口回调阶段
        Bean初始化前阶段
            会调用BeanPostProcessor的postProcessBeforeInitialization方法,若返回null,当前方法将结束。
            通常称postProcessBeforeInitialization这个方法为:bean初始化前操作。
        Bean初始化阶段
            调用InitializingBean接口的afterPropertiesSet方法
            调用定义bean的时候指定的初始化方法。
            初始化方法最终会赋值给下面这个字段: org.springframework.beans.factory.support.AbstractBeanDefinition#initMethodName
        Bean初始化后阶段
            调用BeanPostProcessor接口的postProcessAfterInitialization方法,返回null的时候,会中断上面的操作。
            通常称postProcessAfterInitialization这个方法为:bean初始化后置操作。
        Bean初始化完成操作
    阶段10:所有单例bean初始化完成后阶段
        所有单例bean实例化完成之后,spring会回调下面这个接口: SmartInitializingSingleton
    阶段11:Bean的使用阶段
        这个阶段就不说了,调用getBean方法得到了bean之后,大家可以随意使用,任意发挥。
    阶段12:Bean销毁前阶段
        1.触发bean销毁的几种方式:
            1.调用org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#destroyBean
            2.调用org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons
            3.调用ApplicationContext中的close方法
        2.Bean销毁阶段会依次执行
            1.轮询beanPostProcessors列表,如果是DestructionAwareBeanPostProcessor这种类型的,会调用其内部的postProcessBeforeDestruction方法
            2.如果bean实现了org.springframework.beans.factory.DisposableBean接口,会调用这个接口中的destroy方法
            3.调用bean自定义的销毁方法
    阶段13:Bean销毁阶段

Spring系列第24篇:父子容器详解
    1.什么是父子容器? 为什么需要用父子容器? 父子容器如何使用?
        1.spring是父容器,包含dao、service层,springmvc是自容器,只含controller层。
        2.通常我们使用springmvc的时候,采用3层结构,controller层,service层,dao层;父容器中会包含dao层和service层,而子容器中包含的只有controller层;这2个容器组成了父子容器的关系,controller层通常会注入service层的bean。
        3.采用父子容器可以避免有些人在service层去注入controller层的bean,导致整个依赖层次是比较混乱的。
        4.父容器和子容器的需求也是不一样的,比如父容器中需要有事务的支持,会注入一些支持事务的扩展组件,而子容器中controller完全用不到这些,对这些并不关心,子容器中需要注入一下springmvc相关的bean,而这些bean父容器中同样是不会用到的,也是不关心一些东西,将这些相互不关心的东西隔开,可以有效的避免一些不必要的错误,而父子容器加载的速度也会快一些。
    2.springmvc中只使用一个容器是否可以?
        只使用一个容器是可以正常运行的。

Spring系列第25篇:@Value【用法、数据来源、动态刷新】
    1.@Value的用法
        @Value可以标注在字段上面,可以将外部配置文件中的数据,比如可以将数据库的一些配置信息放在配置文件中,然后通过@Value的方式将其注入到bean的一些字段中
    2.@Value数据来源
        1.来源于上面说的配置文件
        2.也可以将配置信息放在db或者其他存储介质中,容器启动的时候,可以将这些信息加载到Environment中,@Value中应用的值最终是通过Environment来解析的,所以只需要扩展一下Environment就可以实现了。
    3.@Value动态刷新的问题
        1.动态@Value实现的关键是@Scope中proxyMode参数,值为ScopedProxyMode.DEFAULT,会生成一个代理,通过这个代理来实现@Value动态刷新的效果,这个地方是关键。
        2.springboot中的@RefreshScope注解源码,和我们上面自定义的@RefreshScope类似,实现原理类似的。

Spring系列第26篇:国际化详解
    1.Spring中国际化怎么用?
        1.spring中国际化是通过MessageSource这个接口来支持的,内部有三个常用方法来获取国际化信息
            String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
            String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;
            String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
        2.常见3个实现类:
            ResourceBundleMessageSource
            这个是基于Java的ResourceBundle基础类实现,允许仅通过资源名加载国际化资源
            ReloadableResourceBundleMessageSource
            这个功能和第一个类的功能类似,多了定时刷新功能,允许在不重启系统的情况下,更新资源的信息
            StaticMessageSource
            它允许通过编程的方式提供国际化信息,一会我们可以通过这个来实现db中存储国际化信息的功能。
        3.Spring中使用国际化的3个步骤
            步骤一:创建国际化文件
            步骤二:向容器中注册一个MessageSource类型的bean,bean名称必须为:messageSource
            步骤三:调用AbstractApplicationContext中的getMessage来获取国际化信息,其内部将交给第二步中注册的messageSource名称的bean进行处理
    2.国际化如何处理资源文件变化的问题?
        spring国际化这块有个实现类,可以检测到配置文件的变化,就可以解决你这个问题
    3.国际化资源配置放在db中如何实现?
        StaticMessageSource支持硬编码的方式配置国际化信息。
    4.自定义bean中使用国际化
        只需实现MessageSourceAware这个接口,spring容器会自动调用这个方法,将MessageSource注入,然后我们就可以使用MessageSource获取国际化信息了。

27.观察者模式
    实现方式:事件驱动模型
    具体实现:事件源 + 事件 + 监听器
            source    ApplicationEvent    ApplicationLister
    使用:        事件广播器             +         事件广播器的简单实现
        ApplicationEventMulticaster        SimpleApplicationEventMulticaster

 

展开阅读全文
©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读