Spring重点

Spring的生命周期

spring会基于你当前的类生成BeanDefintion,然后实例化。 BeanDefinition描述了一个bean的实例,包括属性值,构造方法参数值和继承自它的类的更多信息,在Spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition结构存储

  1. 实例化 Instantiation
  2. 属性赋值 Populate
  3. 初始化 Initialization
  4. 销毁 Destruction

四步之间穿插的各种扩展点。如下

第一大类:影响多个Bean的接口

实现了这些接口的Bean会切入到多个Bean的生命周期中。这些接口的功能非常强大,Spring内部扩展也经常使用这些接口,例如自动注入以及AOP的实现都和他们有关。

  • BeanPostProcessor :实例化阶段的前后
    实例化前: 可以控制返回的对象。
    实例化: 推断构造方法
    实例化后: 可以控制是否调用set方法,true调用,false不调用。
@Component
public class MainConfig implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("user")) {
            System.out.println("实例化前");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if ("user".equals(beanName)) {
            System.out.println("实例化后");
        }
        return false;
    }
  • InstantiationAwareBeanPostProcessor 初始化阶段的前后
    初始化前: 可以在初始化之前判断当前方法有无指定的注解,无指定可以选择终止之类的。
    初始化后: 可以进行aop。自动注入等。

第二大类:只调用一次的接口

  • Aware类型的接口 : 所有的Aware方法都是在初始化阶段之前调用的!比如BeanNameAware可以感知到bean在容器的位置并获取值。
  • 生命周期接口InitializingBean 可以自定义初始化方法比如验证注入的值是否是你要的数据。通常很多框架底层跟spring整合都有使用。
    当容器关闭时调用 DisposableBean 实现是 通过循环取所有实现了DisposableBean接口的Bean然后调用其destroy() 方法。对应生命周期的销毁阶段。

简单来说每个类实例的过程都进行切面增强功能,创建完交给容器管理,提高整体的扩展力。是spring的核心底层。

Bean的作用域

在这里插入图片描述

通过@Scope可以设置

单例池、单例Bean、单例模式的区别:

  • 单例Bean不表示Spring容器中只有一个Employee类型的Bean,可以创建多个不同名的Employee类型的Bean。
  • 单例模式是指每次创建的对象都是同一个。
  • 单例池底层是一个ConcurrentHashMap,第一次创建单例对象时,会把它存入ConcurrentHashMap,下次再创建该对象时,会直接从单例池中拿。

BenFactory与ApplicationContext的区别

  • 如果使用ApplicationContext,如果配置的bean是单例,它都会被实例化。好处是可以预先加载,坏处是浪费内存。
  • 当使用BeanFactory实例化对象时,配置的bean不会马上被实例化,而是等到你使用该bean的时候(getBean)才会被实例化。好处是节约内存,坏处是速度比较慢。
  • ApplicationContext继承了BenFactory能够实现更多功能,比如国际化,事件发布。

Bean线程安全问题

  • 单例bean不是线程安全的,因为多个线程共用一个对象,但是通常我们开发使用bean都是无状态的(不会保存数据)某种程度上是线程安全的。但是如果bean有了状态就要去修改bean的作用域保证线程安全了!

循环依赖问题

为什么会出现循环依赖问题?

  • 在Spring中,一个对象不是简单new出来的,而是经历一系列的生命周期。因为这种特殊的创建方式才会产生循环依赖问题。当然,在spring出现循环依赖是很常见,有的场景spring帮我们解决了,有的场景是需要我们自己解决。
  • 两个对象在填充属性时互相依赖对方的bean,而每个bean的需要走完生命周期创建导致无限循环。

常见依赖场景

在这里插入图片描述

单例的循环依赖

@Component
public class AService {
    @Autowired
    private BService b;
}
@Component
public class BService {
    @Autowired
    private AService a;
}

在这里插入图片描述

spring采用缓存来解决循环依赖问题。

在这里插入图片描述

  • singletonObjects 一级缓存: 保存完整的bean实例。
  • earlySingletonObjects 二级缓存: 半成品的bean。
  • singletonFactories三级缓存: 函数式接口判断时什么类型的bean,暴露对象提前代理。

spring是如何解决循环依赖的:

在这里插入图片描述

  • A,B循环依赖,在原有的基础上先暴露一个半成品A也就是加入到三级缓存(三级缓存中的函数式接口判断是否被代理,返回对应类型的对象)供其他对象使用,再去初始化B,初始化B如果发现依赖于A也就是循环依赖就会注入三级缓存中的半成品的A,然后加入二级缓存,填充其他属性,从二级缓存取出数据,放入单例池,完成初始化,移除缓存数据(保持单例)。

为什么要存在三级缓存?

  • 如果只有二级缓存会导致进行AOP拿到的都是普通对象,不能完成AOP的功能。
  • 主要是可以解决循环依赖对象需要提前被aop代理,动态判断拿取对应的对象。

其他场景手动解决方案

  • @DependsOn注解,指定加载先后关系。
  • 使用@Lazy注解,延迟加载。

SpringMVC

执行流程

  1. 用户发送出请求到前端控制器DispatcherServlet
  2. DispatcherServlet收到请求调用HandlerMapping(处理器映射器)。
  3. HandlerMapping找到具体的处理器(可查找xml配置或注解配置),生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet。(HandlerMappeing帮你找到HelloController类,并创建对象)
  4. DispatcherServlet调用HandlerAdapter(处理器适配器)。
  5. HandlerAdapter经过适配调用具体的处理器(Handler/Controller)(调用具体的方法)。
  6. Controller执行完成返回ModelAndView对象。
  7. HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet。
  8. DispatcherServlet将ModelAndView传给ViewReslover(视图解析器)。
  9. ViewReslover解析后返回具体View(视图)。
  10. DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
  11. DispatcherServlet响应用户。

在这里插入图片描述

事务

事务管理方式

  • 程序化事务管理: 在此过程中,在编程的帮助下管理事务。它为您提供极大的灵活性,但维护起来非常困难。
  • 声明式事务管理: 在此,事务管理与业务代码分离。仅使用注解@Transactional或基于 XML的配置来管理事务。
    可以指定方法需要的隔离级别,传播行为,超时。

在这里插入图片描述

传播行为

  • PROPAGATION_REQUIRED(默认): 若当前存在事务,就加入到当前事务中;若当前没有事务,则创建一个新事务。
  • PROPAGATION_REQUIRES_NEW: 总是新建一个事务,若当前存在事务,就将当前事务挂起,直到新事务执行完毕。
  • PROPAGATION_SUPPORTS: 指定的方法支持当前事务,但若当前没有事务,也可以以非事务方式执行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值