Spring

1、Spring概述
  • Spring是一款轻量级的java开发框架。它的核心IOC和AOP。
  • IOC:IOC容器,将对象的创建权交由spring管理,我们需要对象的时候,只需要DI依赖注入即可。解除了类与类之间的耦合。
  • AOP:面向切面编程,底层采用动态代理技术。可以实现在不改变原代码的情况下,对方法进行增强。解除了业务间的耦合。
  • AOP的核心:连接点、切入点、通知、通知类、切面
    连接点:正在执行的方法
    切入点:可以被增强的方法
    通知:增强的功能 通知的种类:(前置通知、后置通知、环绕通知、返回后通知、异常后通知)
    通知类:通知所在的类就是通知类
    切面:描述切入点和通知的关系。
  • AOP的动态代理种类:JDK动态代理、CGLIB动态代理
    JDK动态代理:基于接口的动态代理;目标类必须实现一个接口。
    CGLIB动态代理:基于子类的动态代理;目标类不能是最终类,可以被继承。
2、Spring的常用注解

IOC:
创建bean:@Component、@Controller、@Service、@Repository
注入bean:@Autowired、 @Qualifier、@Value
bean的范围:@Scope
配置类:@Configuration、@Bean
组件扫描:@Import、@ComponentScan
加载配置文件:@PropertySource
AOP:@EnableAspectJAutoProxy
事务:@EnableTransactionManager、@Transactional
定时任务:@EnableSheduling、@Shedulied(cron=“*****?”)
缓存:@EnableCaching、@Cachable(不存在才会存)、@CachPut(存)、@CachEvict(删除key对应的缓存)

3、@Autowired、@Qualifier、@Resource的区别

@Autowired、@Qualifier是Spring提供的注解;@Resource是jdk提供的注解。
@Autowired是按照bean的类型注入,当容器中该类型的bean有多个的话,就需要借助@Qualifier注解按照id注入
@Resource等同于前两个注解相加,既可以依照类型注入,也可以按照id注入。

4、BeanFactory和ApplicationContext有什么区别

BeanFactory是容器的顶层接口,是ApplicationContext的父接口,二者都是用来创建bean对象的。
不同点是BeanFactory是懒加载,即每次初始化不会加载所有的bean,而是等用到哪个bean的时候才会去加载该bean
ApplicationContext是在每次容器初始化时,会加载所有的bean对象到容器中;
ApplicationContext是BeanFactory的子接口,在功能上会更完善。
如继承了
EnvironmentCapable,获取环境变量,如操作系统的key value,配置文件properties的key value
ListableBeanFactory,批量获取bean名字的接口
HierarchicalBeanFactory, 返回父容器实例,查询bean是否存在
MessageSource,,支持国际化
ApplicationEventPublisher, 具有了事件发布的功能。
ResourcePatternResolver,获取资源,资源解析器

5、BeanFactory和FactoryBean的区别

BeanFactory是一个factory,是spring用来创建bean的ioc容器
FactoryBean是一个特殊的bean,它也是用来创建bean的,区别就在于它是用来创建一些较复杂的bean对象,如单例模式的bean,代理对象等。

6、Bean的生命周期、循环依赖
  • 生命周期:
    Bean的生命周期有四个阶段:实例化、属性注入、初始化、销毁
    1.spring容器初始化,会先通过xml配置文件或注解配置的类,得到BeanDefinition对象,放到BeanDefinitionMap中;
    2.遍历BeanDefinitionMap,验证是否单例,是否懒加载;然后通过BeanDefinition创建Bean实例;
    3.对当前Bean进行属性填充
    4.回调实现了Aware接口的方法,如BeanNameAware
    5.调用BeanPostProcessor接口(前缀处理器)的初始化前方法.
    6.调用init初始化方法
    7.调用BeanPostProcessor接口的初始化后方法;此处会进行AOP,如完成代理,发布事件
    8.将创建的bean放到一个map中,即单例池当中
    9.使用bean对象
    10.spring容器关闭时调用Disposable的destroy方法销毁bean对象。
  • 循环依赖:循环依赖是在bean的生命周期的第二、第三步发生的
    - 第二步:创建bean的实例
    创建实例的时候会先到单例池中查找,没有,去二级缓存中查找该对象有没有提前暴露,也没有,会生成一个ObjectFactory的对象并将其暴露到二级缓存中。(这一步就是spring用三级缓存来解决循环依赖问题:一级singletonObjects单例池,二级earlySingletonObjects提前曝光尚未进行属性填充的bean,三级singletonFactories存放bean的工厂对象)
    - 第三步:bean属性的填充
    创建完Bean实例后,对该bean进行属性填充,此处要判断是否存在循环依赖,当前bean实例x填充属性时依赖于y,此时就会去走y的初始化;先判断单例池中是否有y,没有,去二级缓存中查找y对象有没有提前暴露,也没有,会生成一个y的ObjectFactory的对象并将其暴露到二级缓存中,然后对y进行属性填充;当对y进行属性填充的时候,发现y又依赖于x,然后,就会重新走初始化x的流程;而按照上面的流程,这一次在初始化x的时候,就会在二级缓存中得到一个由ObjectFactory创建的x对象,此时,循环依赖结束。
    - 三个问题:
    1.ObjectFactory对象:为什么暴露的是ObjectFactory对象而不是Bean对象本身呢,是因为利于扩展,我们可以利用BeanPostProcessor操作ObjectFactory对象生成我们想要的Bean对象。
    2.支持单例:如果是原型即多例prototype,它在容器初始化的时候不会走Bean的生命周期,而是在用到该Bean的时候才会走,这样在第三步属性填充存在循环依赖的时候,就会无限的创建,依赖,创建,依赖
    3.支持非构造方法注入:如果是构造方法注入,在创建Bean实例的时候,就根本没办法创建对象。因为如果存在循环依赖,就会在创建x对象的时候,要new一个y,而y的构造方法又需要一个new一个x,这样就成了死循环了。
7、bean的两种模式

singleton:单例模式,这是spring创建bean对象默认的模式,即同一个bean对象在ioc容器中只会创建一个实例
prototype:多例模式,和单例模式正好相反,每次调用都会创建一个新的bean对象

8、singleton单例模式如何确保线程安全

线程安全问题是由于多个线程同时操作同一个bean对象,对该对象非静态的成员变量进行写操作,会产生线程安全问题
解决方式有三种种:
第一种:将bean的作用域由单例变成多例,不推荐
第二种:尽量避免在bean对象中定义非静态的成员变量,不太现实
第三种:在bean对象中创建一个ThreadLocal成员变量,将非静态的成员变量保存到ThreadLocal中,变成线程私有。如果需要在多个线程之间共享数据,则需要借助锁确保线程同步。

9、Spring框架的设计模式

工厂模式:spring中的BeanFactroy就是典型的工程模式,是用来创建bean对象的工程
单例模式:spring创建的bean对象默认都是单例的,即容器中该类型的bean对象只会存在一个
代理模式:AOP的底层就运用到了动态代理的方式,来对方法进行增强
模板方法:解决重复代码的问题,如RestTemplate ,一个web http客户端请求的模板工具
观察者模式:定义了对象间一对多的关系,即一个对象发生了变化,那么依赖于它的其他对象在监听到该对象发生变化时,就会更新自己的数据。如ApplicationListener

10、spring事务的实现方式、隔离级别、传播行为
  • 实现方式:
    编码方式:即硬编码,写代码实现,不推荐
    注解方式:即添加注解的方式,添加了@Transactional注解,在调用该类中的方法时,框架底层会为该方法提供事务支持。spring事务底层是基于数据库事务和AOP实现的,首先会为添加了@Transactional注解的方法,创建一个代理对象,为代理对象添加事务,然后调用原方法,会将其与数据库的连接的Autocommit属性设置为false,当方法执行未出现异常就自动提交,当方法执行出现异常就会回滚事务。
  • 隔离级别:
    读未提交
    读已提交:orcal数据库默认
    可重复读:mysql数据库默认
    可串行化
    如果spring配置的事务隔离级别高于数据库的隔离级别,以spring配置的隔离级别为准
  • 传播行为:当前方法对调用者方法事务的态度
    required:有事务就加入,没有就创建
    supports:有事务就加入,没有就以非事务执行
    mandatory:有事务就加入,没有就抛异常
    requires new:不论调用者有没有事务,都会创建新事务
    not supported:不论调用者有没有事务,都以非事务执行
    never:调用者没有事务按非事务执行,有事务就会抛异常
    nested:如果调用者存在事务,则在嵌套事务内执行;没有的话就新建事务
11、spring中的事务什么时候会失效

Spring事务底层是通过AOP的动态代理的方式,对切入点的方法进行增强的。在代理对象方法中开启事务,然后调用切入点方法执行,根据方法的执行情况提交事务或者回滚事务。
1.访问权限问题:方法不是用public修饰的,无法创建代理对象
2.方法用final修饰:无法创建代理对象
3.未被spring管理:添加了事务的方法所在的类,未交由spring管理
4.表不支持事务:MyISAM的数据库存储引擎不支持事务;将数据库的存储引擎改为InnoDB即可
5.错误的传播行为:设置的事务传播行为不支持事务,如never等
6.方法内部调用:添加了事务的方法被本类中的方法调用; 解决:在类中对自己进行依赖注入,然后自己调用自己的方法
7.多线程调用:同一个事务是同一个数据库连接,多线程调用同一个添加了事务的方法会建立多个数据库连接,事务会失效
8.自己吞了异常:在添加了事务的方法中,使用了try…catch捕获了异常,未抛出异常
9.抛出异常与捕获异常不一致:@Transactional的属性rollbackOnly默认是碰到error和RuntimeException才会事务回滚。可将其设置为Exception。
10.嵌套事务回滚多了:添加了事务的方法A中,调用了其他添加了事务的方法B,A方法自己未出现异常,B方法出现了异常,导致A方法回滚。 解决:在A方法中对B方法进行try…catch,B方法出现异常只回滚它自己,不影响A方法的事务。

12、ApplicationContext的refresh方法

容器创建完成之后,调用refresh方法刷新spring应用的上下文
共12步,前6步是创建BeanFactroy对象,后6步是ApplicationContext一些特有的功能。
特有的方法是提供国际化功能、提供发布事件功能、留个子类扩展、准备监听器、初始化单例bean、准备生命周期管理器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值