这些年背过的面试题——Spring篇
阿里妹导读
设计思想&Beans
1、IOC 控制反转
2、AOP 动态代理
3、Bean生命周期
@Overridepublic void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 第一步:刷新前的预处理 prepareRefresh(); //第二步: 获取BeanFactory并注册到 BeanDefitionRegistry ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 第三步:加载BeanFactory的预准备工作(BeanFactory进行一些设置,比如context的类加载器等) prepareBeanFactory(beanFactory); try { // 第四步:完成BeanFactory准备工作后的前置处理工作 postProcessBeanFactory(beanFactory); // 第五步:实例化BeanFactoryPostProcessor接口的Bean invokeBeanFactoryPostProcessors(beanFactory); // 第六步:注册BeanPostProcessor后置处理器,在创建bean的后执行 registerBeanPostProcessors(beanFactory); // 第七步:初始化MessageSource组件(做国际化功能;消息绑定,消息解析); initMessageSource(); // 第八步:注册初始化事件派发器 initApplicationEventMulticaster(); // 第九步:子类重写这个方法,在容器刷新的时候可以自定义逻辑 onRefresh(); // 第十步:注册应用的监听器。就是注册实现了ApplicationListener接口的监听器 registerListeners(); //第十一步:初始化所有剩下的非懒加载的单例bean 初始化创建非懒加载方式的单例Bean实例(未设置属性) finishBeanFactoryInitialization(beanFactory); //第十二步: 完成context的刷新。主要是调用LifecycleProcessor的onRefresh()方法,完成创建 finishRefresh(); } ……}
总结:
实例化 Instantiation 属性赋值 Populate 初始化 Initialization 销毁 Destruction
影响多个Bean
BeanPostProcessor InstantiationAwareBeanPostProcessor
影响单个Bean Aware
实例化一个Bean--也就是我们常说的new;
按照Spring上下文对实例化的Bean进行配置--也就是IOC注入;
如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,也就是根据就是Spring配置文件中Bean的id和name进行传递;
如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现setBeanFactory(BeanFactory)也就是Spring配置文件配置的Spring工厂自身进行传递;
如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,和4传递的信息一样但是因为ApplicationContext是BeanFactory的子接口,所以更加灵活;
如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization()方法,BeanPostProcessor经常被用作是Bean内容的更改,由于这个是在Bean初始化结束时调用那个的方法,也可以被应用于内存或缓存技术;
如果Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法。
如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessAfterInitialization(),打印日志或者三级缓存技术里面的bean升级;
以上工作完成以后就可以应用这个Bean了,那这个Bean是一个Singleton的,所以一般情况下我们调用同一个id的Bean会是在内容地址相同的实例,当然在Spring配置文件中也可以配置非Singleton,这里我们不做赘述。
当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,或者根据spring配置的destroy-method属性,调用实现的destroy()方法
4、Bean作用域
在Bean对象中尽量避免定义可变的成员变量(不太现实);
在类中定义⼀个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中;
5、循环依赖
prototype 原型 bean循环依赖
构造器的循环依赖(构造器注入)
Field 属性的循环依赖(set注入)
其中,构造器的循环依赖问题无法解决,在解决属性循环依赖时,可以使用懒加载,spring采用的是提前暴露对象的方法。
Spring容器初始化ClassA通过构造器初始化对象后提前暴露到Spring容器中的singletonFactorys(三级缓存中)。
ClassA调用setClassB方法,Spring首先尝试从容器中获取ClassB,此时ClassB不存在Spring 容器中。
Spring容器初始化ClassB,ClasssB首先将自己暴露在三级缓存中,然后从Spring容器一级、二级、三级缓存中一次中获取ClassA 。
获取到ClassA后将自己实例化放入单例池中,实例 ClassA通过Spring容器获取到ClassB,完成了自己对象初始化操作。
这样ClassA和ClassB都完成了对象初始化操作,从而解决了循环依赖问题。
Spring注解
1、@SpringBoot
实现 AutowiredAnnotationBeanPostProcessor 类,该类实现了 Spring 框架的一些扩展接口。
实现 BeanFactoryAware 接口使其内部持有了 BeanFactory(可轻松的获取需要依赖的的 Bean)。
实现 MergedBeanDefinitionPostProcessor 接口,实例化Bean 前获取到 里面的 @Autowired 信息并缓存下来;
实现 postProcessPropertyValues 接口, 实例化Bean 后从缓存取出注解信息,通过反射将依赖对象设置到 Bean 属性里面。
class JpaApplication { public static void main(String[] args) { SpringApplication.run(JpaApplication.class, args); }}
@SpringBootApplication注解等同于下面三个注解:
@SpringBootConfiguration: 底层是Configuration注解,说白了就是支持JavaConfig的方式来进行配置
@EnableAutoConfiguration:开启自动配置功能
@ComponentScan:就是扫描注解,默认是扫描当前类下的package
@Import(EnableAutoConfigurationImportSelector.class)public @interface EnableAutoConfiguration
2、@SpringMVC
Controller@RequestMapping 用于映射Web请求 支持将返回值放在response内,而不是一个页面,通常用户返回json数据 允许request的参数在request体中,而不是在直接连接在地址后面。 用于接收路径参数 申明的路径,将注解放在参数中前,即可获取该值,通常作为Restful的接口实现方法。 声明该类为SpringMVC中的
SpringMVC原理
客户端(浏览器)发送请求,直接请求到 DispatcherServlet 。
DispatcherServlet 根据请求信息调⽤ HandlerMapping ,解析请求对应的 Handler 。
解析到对应的 Handler (也就是 Controller 控制器)后,开始由HandlerAdapter 适配器处理。
HandlerAdapter 会根据 Handler 来调⽤真正的处理器开处理请求,并处理相应的业务逻辑。
处理器处理完业务后,会返回⼀个 ModelAndView 对象, Model 是返回的数据对象
ViewResolver 会根据逻辑 View 查找实际的 View 。
DispaterServlet 把返回的 Model 传给 View (视图渲染)。
把 View 返回给请求者(浏览器)
3、@SpringMybatis
@Insert :插入sql ,和xml insert sql语法完全一样@Select :查询sql, 和xml select sql语法完全一样@Update :更新sql, 和xml update sql语法完全一样@Delete :删除sql, 和xml delete sql语法完全一样@Param :入参@Results :设置结果集合@Result :结果@ResultMap :引用结果集合@SelectKey :获取最新插入id
mybatis如何防止sql注入?
4、@Transactional
MANDATORY 支持当前事务,如果当前没有事务,就抛出异常。 NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。 NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。 SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
Spring源码阅读
1、Spring中的设计模式
参与话题讨论赢礼品
你时常焦虑吗?一般是在什么场景,工作或生活?我们是否掉入了“别人贩卖的焦虑”(PUA、35岁危机)的陷阱?
点击阅读原文参加话题讨论,截止2024年1月14日24时,我们将会选出 2 名幸运用户和 2 个优质回答分别获得阿里云开发者无线充电器一个。
微信扫码关注该文公众号作者