Question
- 需要下载jar包?- 是的
- context 命名空间的作用?(context 命名空间在使用启动注解的时候要用到)
- aop 命名空间
- beans, core, context, expression
- 什么是xml文件
IOC (Inversion of Control)
- ICO底层原理:xml解析,工厂模式,反射
- Bean管理
- 创建对象 和 注入属性
- 基于xml配置文件实现
- xml配置文件的创建对象
- Bean 标签中的属性:id,class
- scope = “singleton” / “prototype” (单实例还是多实例)
- init-method,初始化时会调用的方法
- destroy-method,销毁时会调用的方法
- 自动装配:autowire = “byName” / “byType” (不过实际中一般由注解来实现)
- xml配置文件的注入属性:
- set方法注入属性
标签 - 有参构造输入属性
标签 - 内部 bean & 外部 bean 注入对象属性
- 联级赋值,向对象属性的属性赋值
- 注入集合属性:数组、list、set、map -> 在集合中添加对象类型值
- set方法注入属性
- xml配置文件的创建对象
- 基于注解方式实现
- 开启注解 bean 管理的步骤
- 引入 context 命名空间
- 开启组建扫描
- 创建类,在类上添加对象注解
- @Autowired, @Qualifier, @Resource, @Value
- 开启注解 bean 管理的步骤
- 工厂 bean,FactoryBean
- 编写类实现 FactoryBean<> 接口
- 重写当中的 getObject, getObjectType & isSingleton 方法
- 调用 FactoryBean 时得到的是在 getObject 中定义的类实例
- bean 生命周期
- Bean 容器通过配置文件找到该 bean 的定义
- 通过构造器创建 bean 实例
- 为 bean 的属性设置值以及对其他 bean 引用
- 把 bean 实例传递到 bean 后置处理器 BeanPostProcessor中 的 postProcessBeanBeforeInitialization() 方法
- 调用 bean 的初始化方法,由 bean 标签中的 init-method 属性定义
- 把 bean 实例传递到 bean 后置处理器 BeanPostProcessor 中的 postProcessBeanAfterInitialization() 方法,在这里进行Aop
- 获得对象
- 当容器销毁时,调用 bean 的销毁方法,用 bean 标签中的 destroy-method 定义
- note:后置处理器实现 BeanPostProcessor 接口,同样需要放到 bean 容器中才会起作用;如果 bean 容器中没有后置处理器,那么就没有上述步骤的中的第3和第5步
- Spring 实现IOC容器的两个方式
- BeanFactory -> BeanFactory在加载配置文件时不会创建对象,只有在获取对象时才会去创建对象
- ApplicationContext
- ClassPathXmlApplicationContext
notes:
- “所谓依赖注入,就是把底层类作为参数传入上层类,实现上层类对下层类的“控制”” - https://www.zhihu.com/question/23277575/answer/169698662
- IoC 源码分析,https://javadoop.com/post/spring-ioc
AOP (Aspect Oriented Programming)
- 底层原理:动态代理
- JDK 动态代理,创建接口实现类代理对象
- CGLIB 动态代理,创建子类的代理对象
- concepts:连接点、切入点、通知(前置、后置、环绕、异常、最终)、切面
- 前置通知,@Before ( Value = “切入表达式” )
- 后置通知,@AfterReturning
- 最终通知,@After
- 异常通知,@AfterThrowing
- 环绕通知,@Around
- 切入点表达式
- execution ( [限权修饰符] [返回类型] [类全路径] [方法名称] ( [参数列表] ) )
- 可以用 “..” 来代替参数列表,表示任意参数
- 可以用 “*” 来代替其他的元素,表示任意的值
- 相同切入点抽取
- 增强类:增强逻辑(通知)所在的类
- @Component
- @Aspect
- @Order()
Spring 事务管理
@RestController & @Controller
- 传统Spring MVC
- 单独使用@Controller,一般情况下(不使用@ResponseBody)返回一个视图,前后端不分离
- @RestController
- 直接返回 JSON 或者 XML 对象,交由前段独自去处理返回的数据,前后端分离
- @RestController 一定意义上就是省去将 @Responseody 补充到方法中去
- @Controller + @ResponseBody
- 将 @ResponseBody 将在方法的返回值前,指定将返回的数据转换为指定的格式
- @Controller + @ResponseBody = @RestController
注解:@Component,@Service,@Repository,@Controller,@Bean
- @Component,@Service,@Repository,@Controller
- 直接作用在类上 - @Target({ElementType.TYPE})
- 标注了那些需要被装配到 bean 容器中的对象
- 其中:
- @Component - 通用的注解
- @Service - 对应服务层
- @Repository - 对应DAO层
- @Controller - 对应 Spring MVC 控制层
- @Beam
- 标注了那些产生了需要被装配到 bean 容器中对象的方法
- 方法本省不是被装配到容器中,方法产生的对象才是装配的目标
- @Bean 比 @Component 的自定性更强
Spring MVC 工作原理
流程说明(重要):
- 客户端(浏览器)发送请求,直接请求到 DispatcherServlet。
- DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。
- 解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由 HandlerAdapter 适配器处理。
- HandlerAdapter 会根据 Handler 来调用真正的处理器来处理请求,并处理相应的业务逻辑。
- 处理器处理完业务后,会返回一个 ModelAndView 对象,Model 是返回的数据对象,View 是个逻辑上的 View。
- ViewResolver 会根据逻辑 View 查找实际的 View。
- DispaterServlet 把返回的 Model 传给 View(视图渲染)。
- 把 View 返回给请求者(浏览器)
面试问题准备:
什么是Spring?
- Spring 是一个 java 编程领域的轻量级开源框架,它的核心思想是通过工厂模式来管理所有在开发过程中所用到的 bean 对象。我们只需要将用到的工具通过注解或者在 xml 中注册到 IoC 容器中即可,在用到的时候再从容器中调用即可。
Spring 框架的优点
- 方便解耦,简化开发
IoC 和 DI
- IoC (Inversion of Control),就是将对于对象实例的控制权交由 spring 来管理,那么我们只要配置好 xml 文件或者注解就行。IoC 容器来负责管理这些对象以及它们的整个生命周期。
- DI (Dependency Inject),当我们要在一个类中调用另一个类的非静态方法,一般的做法都是在该类内部创建一个被调用类的实例,这样子就造成了两个类之间的依赖关系太强了(高耦合)。DI 就是指将底层类作为参数传入到上层类中,从而降低两者之间的依赖程度。而无论是底层类还是上层类都是由 spring 来帮我们管理,在容器中它们都是以独立的 bean 实例存在的
- 不同的依赖注入方法:
- setter 注入
- 构造器注入
- 静态工厂的方法注入
- 实例工厂的方法注入
完全注解开发
- @Configuration
- @ComponentScan (basePackages = “” )
BeanFactory 和 ApplicationContext 的区别
- 两者都是 spring 中常用的 IoC 容器,它们之间的主要是 BeanFactory 作为最底层的接口,采用的是延迟加载的模式,只有当 bean 对象被调用的时候才会去创建。而 ApplicationContext 不同的是它会在容器启动的时候,一次过将所有 bean 都创建了,那么在之后运行的过程中用到的时候再调用。因为 ApplicationContext 的 bean 是已经创建好的,所以它在运行的时候速度会比较快,不过这也导致了它在启动的时候会较慢点。而且如果某些bean的配置有错的话,在启动的时候就能立刻发现;而如果是BeanFactory,在之后的运行中该出错的bean被调用而创建的时候才会有可能发现错误。
bean 的作用域
- 比较常用的作用域:singleton(单实例) & prototype(多实例),默认值为单实例
- 如果 bean 的作用域是 singleton 的话,那么在容器创建的时候就会一并创建唯一的实例,之后每次调用都会返回该例;如果是 prototype 的话,那么就会在对象被调用的时候再创建对象,每次返回的对象都是不同的
- 通过 xml 文件创建 bean 的话,就在 bean 标签内的 scope 属性选择 bean 的作用域
- 通过注解创建 bean 的话,就在注解的 scope 属性选择
- 其他的作用域:request,session,global-session
bean 单实例的线程安全问题
- 因为容器中一般情况下都是单实例,那么当多个线程对同一个实例进行操作时,就会对其成员属性的读写就会产生线程安全问题。解决这个问题可以将有需要的成员属性改为 ThreadLocal 对象,或者直接将该对象改为 prototype,那么每次请求都会产生一个新的实例,读写操作时的都是不同的对象,自然就不存在线程安全问题
- 一般情况下,我们使用的 Controller、Service、Dao 这些 bean 都是无状态的,不会保存数据,所以也就是线程安全的
bean 的生命周期
@Component 和 @Bean 之间的区别是什么?
- 首先 @Component 是作用于类的,而 @Bean 是作用于方法的
- @Bean 注解的自定义性要比 @Component 强;有某些情况下,例如当我们需要引用第三方库中的类时,就只能通过 @Bean 来实现
spring 管理事务的方式有几种?
- 编程式事务和声明式事务,其中声明式事务又具体分为基于 xml 以及基于注解的声明式事务
- @Transactional,及其属性
- propagation,定义事务传播行为
- isolation,事务隔离级别
- timeout,超时时间
- readonly,是否只读
- rollbackFor,设置要进行回滚的异常类型
- noRollbackFor,设置不需要进行回滚的异常类型
- 完全注解声明式事务管理
- 在配置类加上 @EnableTransactionManagement 注解
- 创建事务管理器
AOP JDK 代理和 CGLIB 代理的不同
解释一下AOP
- AOP 的核心思想就是将可重用的模块封装起来,然后拼接到程序的切面上去
unsolved:
- Spring 中 Bean 的生命周期
- Spring 框架中的设计模式 … …
- Spring 事务
- Spring JPA
一些面试题:
- https://blog.csdn.net/weixin_41768263/article/details/80350779
- https://blog.csdn.net/a745233700/article/details/80959716
- http://www.bjpowernode.com/tutorial_baseinterviewquestions/219.html
- https://www.jianshu.com/p/a5d960c6f6dd
- https://blog.csdn.net/zl1zl2zl3/article/details/81865407
references: