Spring框架入门指南

文章目录

    • Spring特点
    • IoC
    • AOP
    • Spring事务
    • 事务隔离级别
    • Spring注解
    • Spring生命周期
    • Spring创建完毕想要初始化一些操作
    • 注解的使用与开发
    • Spring配置类
    • 加载XML配置文件
    • 静态工厂方法和实例工厂方法
    • 循环依赖(循环引用)
    • 三级缓存解决循环依赖问题
    • SpringAOP延申动态代理
    • BeanFactory和ApplicationContext

Spring特点

在这里插入图片描述
Spring是一个轻量级(核心jar包比较小,但是数量多),非侵入式(框架代码不会侵入业务代码,业务代码也不会实现或继承框架中接口或类)的IoC和AOP容器框架。是为Java应用程序提供基础性服务的一套框架,目的是用于简化企业级应用程序的开发,它使得开发者只需关心业务需求。

IoC

IoC 图解
IoC就是,控制反转,就是将原本自己手动new Bean对象的能力反转给了BeanFactory,当Spring运行的时候就回去配置文件中找配置的bean,然后创建相应的bean。

可以将创建bean的时候,然后依赖注入用到了IoC,这个过程详见bean生命周期,然后这个依赖注入是使用反射实现的。反射可以获取一个类中的对象和属性,然后动态的将对象创建和注入。可以多讲讲反射。

AOP

在这里插入图片描述
面向切面编程,能够将那些与业务无关的模块封装起来,像事务,日志,可以减少系统的重复代码,降低模块间的耦合度,并有利于未来的可维护性和可扩展性。

简单来说AOP就是保证开发者在不破坏源码的情况下,为系统中的业务组件添加功能。其中用到了动态代理。

Spring事务

编程式事务(不推荐使用),通过手动管理事务,实际应用很少使用。

声明式事务,在xml配置文件中直接基于注解,实际是通过AOP实现的。

失效场景:修饰一个非public方法,方法中异常被try catch捕获,数据库不支持事务,不是Spring框架创建的类。

事务隔离级别

使用数据库默认的隔离级别,读未提交(事务读取其他事务未提交的数据),读已提交,可重复读(同义事务中,任何时刻查询的结果一致),依次执行。

Spring注解

@Service、@Repository、@Controller,@Component(表示Spring管理的组件),@Autowired(自动装配依赖注入),@Configuration(标识配置类),@Bean,@Scope(指定Bean作用域),@Transactional(事务),@RequestMapping(请求映射),@Aspect(定义切面)。

@Autowired和@Resource的区别,是一个是spring注解,一个是jdk注解。

Spring生命周期

Bean对象创建–>销毁的一个过程,销毁一般是自动或手动配置,主要说Bean实例化–> 反射创建对象–>Bean称为完整对象,最终存储在单例池(singlentonObjects)中。

  • 实例化阶段:初始化Spring容器,加载xml配置文件,将bean封装为BeanDefinition存储在一个Map集合中,这个集合由BeanFactory管理。讲讲实例化Bean的两种方法,静态工厂方法,实例工厂方法
    • 加载配置文件:Bean工厂会自动识别帮我们创建相应的Bean对象,在加载Bean对象的时候会识别Bean配置的一些属性。
  • 初始化阶段:Bean目前是半成品,遍历Map集合,获取每一个Bean信息,通过反射创建实例对象,对这个bean进行属性注入依赖注入,执行一些接口方法。
    • 依赖注入:依赖注入,就是在配置文件中将Dao直接注入给Service,依赖注入就是说允许程序运行过程中,可以动态的向一个对象中提供他所需要的另一个对象,也就是说程序可以通过IoC动态的为对象注入他所需要的依赖,Spring中的依赖注入是由反射实现的,反射可以获取一个类中的对象和属性,然后动态的将对象创建和注入。注入的话需要两部,在需要注入的bean对象下property配置注入,然后在需要注入的类中创建set方法接收注入的对象。
    • 属性注入:不同类型注入方式不一样,普通属性直接通过set,反射设置,如果是对象,就先去找这个bean是否初始化,没有的话先去初始化这个依赖的bean,成功后再去初始化当前bean对象,还有可能出现双向对象引用属性,就出现了循环依赖问题(循环引用)。先讲讲循环依赖是什么 ,然后讲解决办法三级缓存
    • 三级缓存:都是用来存储bean对象,一级缓存singletonObjects存储的是完全创建的对象,二级缓存earlySingletonObjects存储引用的半成品对象,三级缓存singletonFactories存储未被引用的半成品对象。
  • 完全阶段:将创建好的对象存放在单例池singletonObjects中,也是由BeanFactory进行管理,调用getBean会获取相应bean信息。

Spring创建完毕想要初始化一些操作

  1. 创建一个方法,在配置Bean的时候使用init-method进行调用
  2. 实现InitializingBean接口,然后重写afterPropertiesSet接口

注解的使用与开发

@Component替换bean标签,之前启动时会先去xml中加载bean,现在优先加载@Component注解。凡是被@Component注解标识的类,会在指定范围内被Spring加载并实例化。

使用注解标签可以替换bean上面的配置,使得Spring加载更加的便洁,在使用上,之前配置xml文件,配置bean对象的话是需要在bean的配置上配置相应的功能,比如scope,在使用注解时直接使用@Scope注解标签向需要标注的方法上标注作用范围,在bean中的lazy-init在注解标签中使用@Lazy,bean中的init-method在注解中直接向需要加载的方法上标注@PostConstruct,bean中的destroy-method在注解标签中使用@PreDestroy直接在对应的方法上标记。

Spring配置类

配置类用来替代配置文件,使用@Configuration注解标签标识,在配置类中配置相应的配置,然后使用注解方式加载Spring的核心配置类,省去了写xml配置文件,相当于将需要的配置使用相应的注解全部配置在配置类中,然后启动时直接加载配置类就行。

加载XML配置文件

  • 像scope可以设置单例(singleton),原型(prototype),在Spring容器创建的时候,就会对Bean进行实例化,并存储到容器内部,每次getBean获取的都是相同的Bean,而使用prototype,这个是原型的,Spring容器初始化时不会创建Bean实例,当调用getBean时才会实例化Bean,每次getBean都会创建一个新的Bean实例。
  • 设置lazy-init,也就是Bean的延迟加载,也就是当Spring创建容器的时候,不会立刻创建Bean实例,等待用到时再创建Bean实例并存储到单例池中去,后续再使用该Bean直接从单例池获取即可,本质上Bean还是单例的。
  • init-method,Bean实例化后执行的初始化方法,method是指定方法名,destroy-method,就是Bean实例销毁前的方法。(这两种可以使用实现InitializingBean接口,重写afterPropertiesSet方法进行替换)
  • destroy-method,就是Bean实例销毁前的方法,method指定的就是是方法名,初始化方法和销毁方法,销毁时要显式的去销毁调用close,然后关闭容器,bean方法就全部销毁,不然默认不会销毁。
  • 标签使用:
    • bean: Spring中的最基本的标签,用于定义bean,里面有id,name,class,scope,init-method,destroy-method,lazy-init
    • property: 用于在bean中配置属性,就是通过此标签可以直接将属性值设置到bean对象中
    • constructor-arg: 用于在Bean中配置构造函数参数
    • import: 用于导入其他Spring的配置文件
    • annotation: 用于启动bean的自动装配和依赖注入功能
    • alias: 用于为bean指定一个别名,方便使用时引用
    • 自定义标签:在创建Spring容器中,一般都是先加载xml文件,我们引入的一些工具需要在xml文件头中使用链接的方式导入进来,然后用标签使用,在引入过程中,他会给引入的链接设置别名,这个时候将所有的别名进行修改,就可以修改其命名。

静态工厂方法和实例工厂方法

  • 静态工厂方法是静态的,在配置的时候不需要创建对象,可以直接使用类调用,创建一个类,其中定义一个静态方法,其中的返回值就是需要创建的对象,在配置bean的时候,在默认情况下会寻找这个类的构造方法,然后创建这个类的对象,但是我们要实现静态工厂的实例化,那么就在配置的时候使用factory-method,指向创建的静态方法,然后在初始化的时候就会默认调用这个静态方法,去创建这个静态方法返回的对象,并且还可以在这个Bean创建之前可以进行一些其他业务操作。
  • 实例工厂方法必须先有工厂对象,然后通过工厂对象去调用相应的实例方法,实现FactoryBean接口,然后重写getObject和getObjectType方法,在创建对象的时候会发现,存储在BeanFactory里面的是MyBeanFactory2的工厂对象。

循环依赖(循环引用)

注入双向对象引用属性,就是两个对象相互引用,在注入过程中,当某一个Bean执行过程中另一个Bean没有执行,创建了第一个bean的对象后(内存中存在,singletonObjects中没有),然后第一个Bean需要进行属性注入,发现第二个bean没有创建,然后暂停创建第二个bean,这时候第二个bean 同样执行创建对象,然后依赖注入,发现单例池中没有第一个bean,这时候就会暂停去创建第一个bean,这时候就造成循环引用问题,这时候想要解决就需要第二个bean注入第一个bean的时候不用去单例池中去查找,需要直接将第一个bean创建对象时的地址直接引用进来,然后继续走后面的流程,两者都会解决这个循环依赖问题。这个时候就需要使用三级缓存这个是Spring提供的专门解决循环依赖问题的。

三级缓存解决循环依赖问题

因此初始化阶段如果遇到循环依赖问题,Spring中会使用三级缓存解决,在三级缓存中,有个类singletonFactories用来存储创建的对象,但是存储的是半成品对象,且没有被引用,二级缓存(earlySingletonObjects)存储的是新创建的对象,但是已经被引用,一级缓存存储的是已经创建完成的对象。在解决循环依赖时,当第一个bean创建对象,存储在三级缓存中,然后第一个bean进行属性注入时,去三个缓存中搜索第二个bean,发现没有,所以需要去创建,创建了第二个bean对象,存储在三级缓存中,然后第二个bean去注入第一个bean,去三个缓存中寻找,在第三个缓存中找到,然后进行注入,将第一个bean从三级缓存放入二级缓存,然后继续第二个bean的生命周期,直到完全创建成功,创建完成的第二个bean放入一级缓存,然后删除二三缓存中的第二个bean,然后继续执行第一个bean,将第二个bean注入第一个bean中,然后执行剩余的生命周期,完成第一个bean的创建,将其存入一级缓存,然后删除二三缓存中的第一个bean。

SpringAOP延申动态代理

  • AOP面向切面编程,面向对象OOP是对一个事物的抽象,一个对象包括静态的属性信息、动态的方法信息等。而AOP是横向的,是对不同事物的抽象,属性与属性,方法与方法,对象与对象都可以组成一个切面,这种思维去设计编程就是面向切面编程,要想实现这一思想,就需要使用到动态代理,动态代理就是无侵入式的给代码增加新的功能,通过接口保证后面的对象和代理实现同一个接口,接口就是被代理的所有方法,然后代理类可以对需要代理的对象增加新的功能,代理同名方法内的同时,可以执行原有逻辑同时嵌入其他逻辑或其他对象方法。

  • 之前知道动态代理,就是将一个类的需要代理的方法通过创建一个接口,然后实现代理类的方式去创建代理对象,然后向代理对象中添加新的功能或者其他对象中的方法来实现动态代理的功能。但是面向切面中有以下几点概念,有:目标对象,代理对象,连接点,切入点,同时/增强功能,还有切面,其中目标对象就是需要进行增强,进行代理的对象,连接点就是其中的方法,切入点就是其中需要进行代理的方法,代理对象就是使用Proxy对象来进行代理,将需要代理的方法传入Proxy的参数中,通知/增强部分就是需要添加的方法或事件,切面部分是对于每一个被增强的方法而言的。

  • 在Spring中在调用getProxy方法的时候,可以选用的AopProxy接口有两个实现类,一种是基于JDK的,另一种是基于Cglib的

    首选的都是jdk基于接口的,就是目标类有接口,基于接口实现动态规划,生成实现类的对象,这种是目标类有接口的情况下,默认方式。

    其次是Cglib动态代理,使用Cglib的情况就是当这个目标类没有接口的时候,这个时候系统自动创建一个类去继承这个目标类,然后在创建的类中去实现增强功能,这种方式是当目标类没有接口的情况下默认实现,目标类有接口的时候,想要使用需要手动配置。

BeanFactory和ApplicationContext

BeanFactory是Spring早期的接口,是Bean工厂,主要是管理Bean,而ApplicationContext是后期更高级的接口,称为Spring容器。ApplicationContext是对BeanFactory基础的功能上进行了扩展,BeanFactory的API更偏向于底层,而ApplicationContext的API更像是将底层API进行封装;Bean的创建的主要逻辑和功能都被封装在BeanFactory中,所以ApplicationContext继承BeanFactory,又维护着BeanFactory的引用,就说说BeanFactory是ApplicationContext中的一个属性。最后就是两者的对于Bean的初始化的时机不同,原始BeanFactory是在首次调用getBean是才进行创建,而ApplicationContext是在配置文件加载,容器一创建就将Bean都实例化并初始化好的。

你可能感兴趣的:(常用框架,spring,java,后端)