Spring第一次复学日记

bean属性:

        bean的id默认不设置的话是类的全限定名,底层由一个singletonObjects的map来维护单例bean,key是id默认是全限定名,value是bean实例。然后别名通过一个aliasMap维护,别名为key,value为对应的key值。这样一看查找bean的操作就十分清晰了,先去aliasMap里用键去查,没查到就直接用这个键值去查singletonObjects,查到了就用aliasMap里的value去查singletonObjects。注意如果没有配id的话,首先默认是别名的第一个,如果没有别名才使用全限定名。

bean的作用范围

        一个是单例,一个是原型,单例就是singleton,每次去拿bean,拿的都是开始创建好的,在Spring容器初始化时,就创建好了。而prototype,在初始化时并不会创建该bean,而是每拿一次bean就创建一次,创建一个新的bean。

        当在springMVC环境下还会有request和session 

bean的懒加载lazy-init

        当设置懒加载(延迟加载)后,不会在spring容器初始化的时候就创建bean,而是懒汉式,等到调用的时候再去创建bean到spring容器

 bean的初始化和销毁方法

        直接通过xml或注解bean指定初始化方法和销毁方法即可,销毁方法在容器销毁时被调用。InitializingBean接口中有一个afterPropertiesSet()方法,这个方法在bean创建操作即set方法之后,init方法之前。

bean的实例化

        spring的实例化方式主要有两种,一种是构造方式实例化,通过构造方法完成实例化,一种是工厂方式实例化,通过工厂方法完成实例化。

        工厂方式又分为静态工厂方法实例化bean,实例工厂方法实例化bean,实现FactoryBean规范延迟实例化bean。静态工厂属于类,所以不需要对工厂类进行实例化,但实例工厂方法属于对象,所以进行bean实例化时,必须先对工厂类进行实例化。

        实现FactoryBean规范延迟实例化bean在singletonObjects的value是工厂对象,FactoryBeanObjectCache中的map对应的value是被实例化的bean。

bean的自动装配

        分为根据type进行装配还有name进行装配,name更细,type适用性更强,但面对多个实现会报错。

bean的实例化流程

        spring容器初始化时,会把bean信息封装成一个BeanDefinition对象,spring根据该对象创建Bean对象然后存储在singletonObjectes中去

Spring的后处理器

        有两种后处理器,当然这两个都是接口,分别是BeanFactoryPostProcessor,它是Bean工厂后处理器,他的调用时机在所有bean信息封装成一个BeanDefinition对象完成之后,Bean被创建成对象之前;然后是BeanPostProcessor,它是Bean后处理器,它在每个Bean的实例化之后调用,也就是把BeanDefinition对象创建成Bean之后,在填充到singletonObjects之前。有多个相同接口的后处理器的时候,子类的有优先调用。

        注解开发的时候,常常用到一个包扫描器和一个标志注解(比如@Component),包扫描器负责扫描获得该包下使用该@Component注解的,全限定名和Class,然后通过BeanFactoryPostProcessor后处理器,进行动态注册。

        BeanPostProcessor中的俩个方法,postProcessBeforeInitialization和postProcessAfterInitialization,先是postProcessBeforeInitialization方法中间夹着属性设置方法也就是继承的InitializingBean接口的方法然后是init方法,最后方法再是postProcessAfterInitialization

Bean创建的生命周期

        Bean开始创建前叫做实例化阶段,Spring会根据BeanDefinition的信息来创建Bean,比如是否立即创建根据延迟加载属性。需要注入的信息通过BeanDefinition的属性properyValues进行存储。

        然后Bean开始进行初始化,此时的Bean,也就只分配了内存(外壳),还并没有进行属性填充,执行一系列Spring定义的接口方法比如postProcessBeforeInitialization,InitializingBean,Aware接口等。属性填充分为以下几种情况:

  • 注入普通属性,String、int这种可以直接赋值的类型,直接set注入
  • 注入单向引用的对象属性时,也是通过set方法反射注入进去,若容器内还没有,就创建一个。
  • 面对双向引用,循环依赖的问题,需要引用earlySingletonObjects,缓存来解决循环依赖问题。

        初始化完成后被放到单例池singletonObjects中。

循环依赖和三级缓存

        先用没有缓存的思想去过一遍循环依赖问题,假如我有两个bean,分别为A和B,A依赖B,B又依赖A,填充A属性时,遇到B,就去singletonObjects里找,有没有,结果没有,就去创建B,但是B里又要填充A属性,导致无限递归。

        从而产生三级缓存架构,重新带入该问题,填充A属性时,遇到B,就去singletonObjects里找,有没有,有就返回,没有就在二级缓存earlysingletonObjects里找,有就返回,没有去三级缓存SingletonFactories(里面存的是获取对象的工厂)创建一个bean返回到二级缓存中, 然后直接得到这个半成品的bean,由于是浅拷贝,属性是传递的,所以说无需关心后续,A成为完成品的bean时,B里的A也会完成。然后B就算创建成功,然后A中的B属性也就算填充成功,解决问题。

        有一个点很重要,明明两级缓存就能解决,为啥还有使用三级缓存,这是为了解决代理问题的。

注解注意事项

        @Autowired根据类型进行注入,如果同一类型的Bean有多个,就尝试根据名字进行二次匹配。名字就是要注入的变量名去匹配Bean的名称。当要匹配Bean名字时,要使用@Autowired和@Qualifier组合使用或者@Resource(name = ""),Resource注解原本是jdk里的注解,被Spring增强过了。

        在局部参数中注入bean,直接使用@Qualifier即可,或不写,自动省略@Autowired。

        @Primary注解,可以在根据类型获取bean,且有多个该类型的bean时,将使用了@Primary注解的Bean的优先级提升。

        @Profile标注在类或方法上,标注该Bean在什么环境下才会被注入。

spring的组件扫描功能,xml使用的是自定义命名空间解决的,注解是使用BeanFactoryPostProcessor解决的,算法都一样。

        @import可以导入三种类,普通的配置类,就是@Configuration配置类,以及实现了ImportSelector接口或ImportBeanDefinitionRegistrar接口的类,
这两个接口可以注册bean。

AOP里的一些概念       

        Target是被增强的目标对象;Proxy是对Target进行增强的代理对象,也是最终所调用的;Joinpoint连接点,就是Target中可以被代理(增强)的方法;Pointcut是实际上被代理(增强)的方法;Advice是增强的代码部分;Aspect切面,就是在某个Pointcut上的某个Advice就叫做一个切面;Weaving织入讲的就是这个动态代理(增强)的过程。

        主要分为五种类型的通知,前置,后置,环绕,异常,最终,这五种通知。还可以传递三种参数,JoinPoint是连接点对象,五种通知都可以使用,可以获得连接点所属对象,方法的信息。ProceedingJoinPoint,主要在环绕通知中执行原本方法。Throwable是异常对象,用在异常通知里,需要在配置文件中指出异常名字(异常参数名)。

        使用@EnableAspectJAutoProxy,用注解方式开启注解式AOP功能。

事务控制

        编程式事务主要有三个类,平台事务管理器(PlatformTransactionManager),这是一个接口,不同平台orm框架实现可能不同,其实现类具备事务提交、回滚、获取事务对象的功能;事务定义(TransactionDefinition),它封装了事物的隔离级别、传播行为、过期时间等属性信息;事务状态(TransactionStatus),它存储着当前事物的状态信息,比如事务是否提交、是否回滚、是否有回滚点等。

        Xml事务配置,先配置想要事务增强的aop,里面配置一个pointcut,配置一个advisor,依赖一个advice,然后配置这个spring提供的advice,这个advice由一个PlatformTransactionManager管理,最后配置这个事务管理器(PlatformTransactionManager)及其里面的dataSource。

        学到这里对于@EnableTransactionManagement的理解就更进一步了,他就是去找一个transactionManager的Bean,在Springboot中就通过yml文件自动注入了这个bean,然后就是找注解所修饰的方法,然后AOP事务,动态代理。

你可能感兴趣的:(学习记录,spring,java,前端)