框架部分面试题学习

IOC容器,AOP

  1. IOC :依赖反转,将对象的创建,组装,管理的控制权限从应用程序反转到IOC容器中。由springboot的来实现对象的自动装配和注入。
    1. 当某个类使用了@Componnet 注解后,标记为一个组件。那么这个类在项目启动的时候,会自动执行Bean装配,生成一个Bean对象到依赖池中。
    2. 当在其他的类中使用了@Auotwired 注解后,会执行bean加载(依赖注入),将依赖池中的对象拿出来。
    3. IOC装配·Bean 的详细流程为:
      1. 创建一个BeanFactory ,加载配置文件。根据配置文件,创建BeanDefination 对象。
      2. 将BeanDefination 对象注册到 Bean工厂中 ,根具 BeanDefination 信息,进行Bean实例化,得到空的Bean 实例。
      3. 使用@Auotwired 自动将依赖注入到Bean实例中。
      4. 进行Bean的初始化,得到可用的bean实例,检查依赖关系,添加到依赖池中。
  2. AOP :面向切面编程。 在不修改原来的代码的基础上,在目标方法中增加新的功能或者拦截原有的功能实现。解决代码的耦合度与代码复用的问题。
    1. 底层使用了JDK+CGLIB的动态代理方式实现。
    2. 定义切面: 首先的定义i一个切面类,使用@Component 、@Aspect 注解。
    3. @Pointcut 在切面中,定义一个切入点:定位到想要去拦截或添加功能的位置方法上。
    4. @Before :定义切入点到目标方法执行前的方法。
    5. @AfterReturning :目标方法执行无异常结束后执行。
    6. @After :目标方法执行出现异常后执行
    7. @AfterThrowing :目标方法出现异常时执行的方法
    8. @Around ():环绕通知,使用rtry-catc的方法实现,方法的执行前后的通知。
    9. 最后使用切点定位目标方法的过程叫做织入,会生成一个代理对象,执行切面的方法。
xml 复制代码
/**
 * 切⾯
*  
切⼊点和通知的抽象   (与⾯向对象中的 类 相似)
*  
定义 切⼊点和通知 (切⼊点定义了要拦截哪些类的哪些⽅法,通知则定义了拦截过⽅法后要做什么)
*/
 @Component // 将对象交给IOC容器去实例化
@Aspect // 声明当前类是⼀个切⾯
public class LogCut {
 /**
 *  
*      
*  
切⼊点:
匹配规则。规定什么⽅法被拦截、需要处理什么⽅法
定义切⼊点
*    @Pointcut("匹配规则")
 *
 *    Aop 切⼊点表达式简介
*       1. 执⾏任意公共⽅法:
*        
execution(public *(..))
 *       2. 执⾏任意的set⽅法
*        
execution(* set*(..))
 *    
*        
 3. 执⾏com.xxxx.service包下任意类的任意⽅法
execution(* com.xxxx.service.*.*(..))
*       4. 执⾏com.xxxx.service 包 以及⼦包下任意类的任意⽅法
*        
execution(* com.xxxx.service..*.*(..))
 *
 *       
*      
注:表达式中的第⼀个* 代表的是⽅法的修饰范围
可选值:private、protected、public (* 表示所有范围)   
*/
 @Pointcut("execution (* com.xxxx.service..*.*(..) )")
 public void cut(){}
 /**
 * 声明前置通知   并将通知应⽤到定义的切⼊点上
* ⽬标类⽅法执⾏前 执⾏该通知
*
 */
 @Before(value = "cut()")
 public void before() {
 System.out.println("前置通知.....");
    }
 /**
 * 声明返回通知   并将通知应⽤到定义的切⼊点上
* ⽬标类⽅法(⽆异常)执⾏后 执⾏该通知
*
 */
 @AfterReturning(value = "cut()")
 public void afterReturn() {
 System.out.println("返回通知.....");
    }
 /**
 * 声明最终通知   并将通知应⽤到定义的切⼊点上
* ⽬标类⽅法(⽆异常或有异常)执⾏后 执⾏该通知
*
 */
 @After(value = "cut()")
 public void after() {
 System.out.println("最终通知.....");
    }
 /**
 *  
*  
*      
/**
 * 声明异常通知   并将通知应⽤到定义的切⼊点上
* ⽬标类⽅法出现异常时 执⾏该通知
*/
 @AfterThrowing(value="cut()",throwing = "e")
 public void afterThrow(Exception e) {
 System.out.println("异常通知....." + "  异常原因:" + e.getCause());
    }
声明环绕通知  并将通知应⽤到切⼊点上
⽅法执⾏前后  通过环绕通知定义相应处理
需要通过显式调⽤对应的⽅法,否则⽆法访问指定⽅法 (pjp.proceed();)
* @param pjp
 * @return
 */
 @Around(value = "cut()")
 public Object around(ProceedingJoinPoint pjp) {
 System.out.println("前置通知...");
 Object object = null;
 try {
 object = pjp.proceed();
 System.out.println(pjp.getTarget() + "======" + pjp.getSignature());
 // System.out.println("返回通知...");
        } 
catch (Throwable throwable) {
 throwable.printStackTrace();
 System.out.println("异常通知...");
        }
 System.out.println("最终通知...");
 return object;
    }
 }

Bean对象的循环依赖问题是什么,怎么解决

  1. 当两个类相互注入时,当spring尝试创建其中一个对象,发现依赖于另一个,先去创建其对象。
  2. 解决:
    1. 使用了springboot得的二,三级缓存,将没有完全实例化好的对象存储在二级缓存中,当出现循环依赖时,会在二级缓存中找到未实例化好的对象。
    2. 的当出现AOP的循环依赖问题,三级缓存中存在多对多每个Bean都beanFactory ,通过getObject()可以获得未完全实例化好得到bean .存到二级缓存中。

AOP的使用场景有哪些,如果让你去模拟一个怎么进行实现

  1. 日志打印、性能分析、安全控制、事务处理、
  2. @EnableAspectJAutoProxy 在启动类上添加注解选择代理模式。用于开启基于 AspectJ 的自动代理功能
  3. 写一个切面类(日志打印),@component @Aspect标记该切面类中 。
  4. 在切面类中 定义切点@pointcut("execution()")找到目标方法。(通过@interface 去实现自定义注解,匹配规则中,写下先自定义注解的全路径,通过自定义注解找到对应的目标方法)
  5. 切面中实现@before ("切入点") @After() @AfterThrowing() @AfterRunner @Around()

Spring事务回滚流程

  1. spring事务通过Aop 来实现,先创建一个代理对象,根据aop的流程执行具体的逻辑操作。但是不通过aop的通知实现核心操作,而通过transacationlnterceptor来实现,调用invoker()方法实现具体的逻辑。
  2. 具体流程可以描述为:
    1. 先做准备工作,解析@Transaction注解的目标方法上的事务相关的属性,根据属性或者根据配置文件 中的事务管理器 (DataSourceTransactionManager)启动事务。当事务启动,其他的sq会等待事务结束在执行。
    2. 当开启事物,获取数据库连接,将数据库的自动提交模式设置为false.
    3. 执行具体的业务逻辑操作。如果执行成功,将自动提交模式设置为true ,释放数据库连接资源。
    4. 当操作执行失败,抛出异常,如果异常是一个runTimeException或error 通过completeTransaction 完成事务的回滚。否则不回滚事务。除非@Transaction()中指定提交指定了rollbackfor 。 具体是通过doRollBack实现。
    5. 事务执行完成后,通过cleanupTransaction清除相关事务操作。

什么情况下事务会失效

  1. @Transactionnal 注解只能使用public的方法使用。
    1. 非public方法可能无法抛出或捕获异常。
    2. 访问权限,无法被外部方法调用。
    3. 事务是同过aop 代理方式实现,非public 的方法可能不能被拦截。
  2. 通过类 内部普通方法对 @Transactional注解的方法进行调用。
    1. 事务的开始结束,在service的最外层,内部发生可能导致,事务的范围不准确。
    2. 导致事务的隔离级别不正确。
    3. 异常未正确处理的不能正常回滚。
    4. 导致数据库连接异常。事务不能正确进行。
    5. 并发异常。
  3. 数据库不支持事务。
    1. 使用了Myisam 。
  4. @transactional 默认只处理运行时的异常,进行回滚。通过rollbackFor 和norollbackFor 指定哪些异常需要回滚。
  5. 事务的传播属性设置不正确。以never 、not_supported 不生效
    1. Required :默认的传播机制,存在支持当前的事务,不存在创建一个新的。
    2. Supports:事务存在支持事务,不存在,支持非事务。
    3. Mandatory:在正常的事务内执行,否则抛出异常。
    4. Requires_new:不管存不存在,直接开启一个新事务。
    5. Not_supported:只能以非事物执行。
    6. Never:只能以非事物执行。存在事物抛异常。
    7. Nested :不存在,开启事务,存在事务,运行一个嵌套事务。
  6. 捕获异常未抛出。导致事务终止。
    1. 捕获异常后未回滚、提交
    2. 捕获异常后未记录日志或通知。
    3. 捕获异常后未处理或重新抛出。
  7. Bean没有被Spring容器管理。
  8. 事务的方法内启动新线程来进行异步操作。
    1. 新线程异步操作在事务提交之前,导致事务不能提交。
    2. 新线程的一部操做在事务的内部,并且事务的传播机制未supprot_new,会开启新的事物,与原事物无关。
    3. 新线程的异步操作出现异常未处理,原事物订单不能回滚。

怎么证明你这个Controller方法是单例的

  1. 对控制器的构造方法使用日志打印,发起多次请求后,发现打印的日志只有一条。
java 复制代码
// 创建LOgger对象,调用logger.info()打印日志。
 @SpringBootApplication
 public class Starter {
 private static Logger logger = LoggerFactory.getLogger(Starter.class);
 }
 public static void main(String[] args) {
 logger.info("SpringBoot 应用开始启动...");
 SpringApplication.run(Starter.class);
    }
  1. 对该方法打断点,多次发起请求,查看对象是否是同一个。

Spring的七大核心组件分别是哪些

  1. spring core :核心容器创建和管理bean的容器。
  2. springcontext :spring上下文配置文件,向spring提供上下文信息。
  3. spring Aop
  4. spring dao 用于访问数据的对象
  5. spring orm : 对象关系映射,解决对象与数据库不匹配的问题。
  6. spring web : 为基于web的应用程序提供上下文。
  7. spring mvc :spring 内置的MVC 框架。解决了web开发常见的问题,参数接受、文件上传。支持restful 风格的URL 请求路劲。

IOC和AOP理解

一二三级缓存分别存储什么信息

  1. concurrentHashMap 存储完整创建的实例Bean ,当需要用时可以快速获取。
  2. ConcurrentHashMap 暂时未完成创建好的bean 对象。循环依赖中出现。
  3. concurrentHashMap 三级存储了一个bean工厂,在需要创建bean的时候来创建bean 对象。

详细的日志信息怎么得到

  1. springboot默认使用LogBack 日志系统。在yml 或 properties 文件中将日志输出的级别提高到Debug。
properties 复制代码
logging.level.root=DEBUG
  1. 配置其他的日志系统--Log4J。

拦截器是怎么实现拦截的

  1. 首先先创建一个拦截器对象。实现interceptror 是接口,重写他的三个方法 preHandel()hostHandel()afterComletion()。
  2. 配置拦截器:实现WebMvcConfiguration 接口。通过重写addinterceptors() 方法添加多个拦截器,的使用拦截器对象的addpathpatterns("/")添加拦截路经。

Spring中配置过滤器

  1. 实现Filter接口,重写三个方法 init() 、dofilter()、destroy(),在实现类上使用@webFilter注解定义过滤路劲。
  2. 在启动类上添加@ServeltCompenetScan 进行自动配置。

Cookie,Session,Token三者的区别与使用

  1. cookie:存储在客户端的小文本数据 。安全性较低,cokie可以被直接获取。存储一些非敏感、与用户会话相关的小量信息当客户端访问服务器,服务器会发送给cookie到客户端存储,当下次访问时会带着cookie一起访问。服务器会响应对应的数据。
  2. session:存储在服务器中,当客户端访问服务器,服务器存储客户端的数据,返回一个session ID 到客户端。客户端带着这个id 访问服务器 ,服务器通过id找到对应的session,就能给出这个session 对应的客户端数据。安全性较高,存储用户的相关信息。
  3. token: 存储在客户端,通常是一个包含用户信息和签名的字符串.
  4. 客户端带着token 到服务器,服务器验证token ,返回true,则返回客户端数据。安全性主要看加密强度强弱。存储用户的权限标识。

MVC执行流程

  1. 用户发出请求->被前端控制器(dispatcherServlet)拦截。,调用处理器映射器(handerMapping)
  2. 处理器映射器去找到的具体的处理器(xml配置或注解),生成处理器对象、处理器拦截器,返回给前端控制器。
  3. 前端控制器调用处理器适配器(handerAdapter)去调用具体的处理器(handler\controller )
  4. 具体的处理器执行返回ModelAndView 视图对象给处理器适配器。再返回给前端控制器。
  5. 前端控制器将视图给视图解析器(ViewReslover)解析,将解析的结果 View 返回给前端控制器。
  6. 前端控制器将视图进行渲染后返回给用户。

Controller层有哪些常用的注解,前端传给后端的数据应该通过哪些注解接收的

  1. 前端到后端的数据:
    1. @RequestBody() : 解析json 格式,并将其转换为相应的java格式
    2. @Requestparmar /@modelTribute /@RequestPart 接收前端传来的参数绑定到java 对象上。
    3. @PathVariable :接收URL路劲上的参数.
    4. @RequestHeader :获取请求头上的某个字段。
    5. @XmlrootElement: 处理Xml数据与java对象之间的转换

前端发送到后端的对象是如何变成一个实体类的,后端返回给前端的实体类又是如何变成JSON字符串

  1. 前端将对象序列化为jon字符串,这个字符串中包含了对象的属性与值。
  2. 后端使用@RequestBody 注解标识实体,内置的解析器将json字符串中的属性与值通过反射来设置该对象。
  3. springboot 默认使用jackson 来处理序列化。当controller 返回数据时,自动调用jackson 序列化数据。使用阿里提供的--fastjson

SSM中涉及到哪些设计模式

  1. spring :
    1. BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
      单例模式:Bean默认为单例模式。
      代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
      模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
      观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现--ApplicationListener。
  2. springMVC :
    1. 组合模式:
    2. 责任链模式:过滤器链
    3. 策略模式:
    4. 适配器模式
  3. mybatis :
    1. 建造者模式 :
      例如 SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder;

工厂模式 :

例如SqlSessionFactory、ObjectFactory、MapperProxyFactory;

单例模式 :

例如ErrorContext和LogFactory;

代理模式 :

Mybatis实现的核心,比如MapperProxy、ConnectionLogger,用的jdk的动态代理;还有executor.loader包使用了cglib或者javassist达到延迟加载的效果;

组合模式 :

例如SqlNode和各个子类ChooseSqlNode等;动态SQL like、trim等

模板方法模式 :

例如BaseExecutor和SimpleExecutor,还有BaseTypeHandler和所有的子类例如IntegerTypeHandler;

适配器模式 :

例如Log的Mybatis接口和它对jdbc、log4j等各种日志框架的适配实现;

装饰者模式 :

例如cache包中的cache.decorators子包中等各个装饰者的实现;

迭代器模式 :

例如迭代器模式PropertyTokenizer;

简述mybatis中#与$区别

  1. #{} ¥{} 都是当访问maapper 接口时,传递给方法的形参值。
  2. 区别:
    1. 执行过程:#{}:将读取到的参数用?来占用,编译sql ,用得到的值替换? ${}:直接将读取的值替换参数。 参数如果是字符串:#{} 不需要手动添加 ' ' ${}需要,否则报错
    2. sql注入:#{} 预编译先用?替换参数,再用值替换?不出现sql注入。 ${}会出现。
    3. 传递关键字:使用#{} 会自动添加' ' 会报错,${}不会。

mybatis在什么场景使用,mybatis出现取代了什么,没有mybatis的时候怎么处理

  1. 需要频繁操作数据库,复杂的业务场景编写原生sql ,与多种数据库兼容,灵活的对象映射。
  2. 取代了传统的JDBC,开启jdbc,执行sql语句,关闭数据库连接等操作。
  3. mybatis 只需要在maper 文件中写好对应的sql,创建对应的接口。mybatis 会自动处理数据库的连接和释放。
  4. 使用纯JDBC封装。里面编写JDBC的连接、执行、释放等方法。 使用其他的ORM 框架。 数据库的存储过程和视图。

mybatis接收返回值类型怎么设置,有哪些

  1. 输入返回值类型:paremetertype :别名或者 全类名。
    1. _基本类型 : _int
    2. 引用类型:大写转小写。包装类、string ,list 、hashmap。实体类、封装的POJO类。
    3. 多个参数时,可以通过@Param 注解实现多个参数的接收,接受的时候封装为hashmap
  2. 输出返回值类型:resultType:
    1. 类型:_基本类型 : _int
    2. 引用类型:大写转小写。包装类、string ,list 、map、 实体类、封装的POJO类。
  3. resultMap: 自定义的返回类型。当出现数据库的映射出错问题。为字段名起别名。
xml 复制代码
<resultMap id="empDeptMapResultMapOne" type="Emp">
  <id property="eid" column="eid"></id>
  <result property="empName" column="emp_name"></result>
  <result property="age" column="age"></result>
  <result property="sex" column="sex"></result>
  <result property="email" column="email"></result>
  <result column="did" property="dept.did"></result>
  <result column="dname" property="dept.dname"></result>

</resultMap>

<select id="getEmpAndDept" resultMap="empDeptMapResultMapTwo">
  select emp.*,dept.* from emp left join dept on emp.did = dept.did where emp.eid = #{eid}
</select>

Mapper的映射如何设置

  1. 在dao接口定义方法。在mapper.xml文件中实现sql方法。在全局配置文件中映入mappper.xml路经,配置数据库。

Mybatis如何实现多表中实体映射关系

  1. 一对一:存在两张表,将查询的字段封装为一个POJO类
xml 复制代码
<resultMap id="" type = "">
  <id = "" column=""  property="">
  <id = "" column=""  property="">
    <association property="" javaType="">
      <id column = "" property="">
        <result column="" property="">
        <result column="" property="">
        <result column="" property="">
    </association>
</resultMap>
<select id="" RequestMap="">编写sql </select>
<select id="" ResultType="">编写sql </select>
  1. 一对多/多对多:存在两张表以上:
xml 复制代码
<resultMap id="" type = "">
  <id = "" column=""  property="">
  <id = "" column=""  property="">
    <collection property="" oftype="">
      <id column = "" property="">
        <result column="" property="">
        <result column="" property="">
        <result column="" property="">
    </collection>
</resultMap>
<select id="" RequestMap="">编写sql </select>

SpringBoot核心注解

  1. @SpringBootConfiguration : 将类申明为配置类,将当前类中所有以@Bean 标记的方法的实例放到spring 容器中。
  2. @ComponentScan:自动扫描写好的当前路径下的包使用@Component @Controller 、@Service @Repository 注解标记的类。作为 bean 加载到spring容器中。
  3. @EnableAutoConfiguration :自动配置的入口,springBoot更据添加的 jar 包进行项目的配置。

SpringBoot加载Web运用程序的流程

  1. @SpringBootApplication 注解的 启动类 启动时调用 SpringApplication.run() 启动应用程序。
    1. springBoot根据配置好的依赖,进行自动配置,生成web环境需要的Bean.(负责处理web的请求和响应)
    2. springBoot 内置的TomCat会作为默认的 Servlet 容器 ,自动启动。
    3. springBoot自动注册、初始化 前端控制器(DispatcherServlet) 类。、
    4. Spring Boot 会扫描并初始化应用程序中定义的 Web 控制器类(带有 <font style="color:rgb(199, 37, 78);background-color:rgb(249, 242, 244);">@Controller</font><font style="color:rgb(199, 37, 78);background-color:rgb(249, 242, 244);">@RestController</font> 注解的类)。
  2. 前端控制器(DispatcherServlet)根据控制器类的方法上的 URL 映射注解(@RequestMapping、@GetMapping 等)来处理 Web 请求
  3. 如果控制器返回的是一个逻辑视图名,DispatcherServlet 会使用配置好的 视图解析器(ViewResolver) 来解析并渲染该视图。
  4. 最终,处理完请求后的响应数据会通过 Tomcat 容器返回给客户端。

SpringBoot自动装配原理

  1. springboot 提供了一系列的相关起步依赖,里面包含了一组相关的依赖,保证满足spring Boot 的使用·
  2. 大量的自动配置类:它们包含了用于配置 Spring 容器中各种组件的逻辑。在springbootautoconfigure模块的META - INF目录下有一个spring.factories文件,这个文件中定义了一系列的自动配置类的全路径名。当 Spring Boot 启动时,会读取这个文件,找到所有需要加载的自动配置类。
  3. Spring Boot 大量使用条件注解来决定自动配置类是否应该被应用。自动判度是否需要创建自动配置类。
  4. Spring Boot 通过@AutoConfigureOrder注解来控制自动配置类的加载顺序,自动配置类是相互关联的。这个注解是一个整数,数字越小,优先级越高。

SpringBoot的启动流程?

  1. 通过main方法使用springApplication .run()创建springApplication 对象,、
  2. 运行这个springApplication对象,会开始加载环境变量,配置文件、系统属性。将信息存放在Environment对象 中。
  3. 选择合适的上下文。annotationConfigurSpringConText() 或XmlwebConfigurSpringContext ()。然后通过@SpringBootApplication 去扫描对应的组件,注册到上下文环境当中。
  4. 进行自动配置,@EnableAuotConfigurtion 根据配置和依赖去配置相关的组件(配置类)。
  5. 如果是web应用程序,那么会自动去启动内置的tomcat服务器。去配置文件中设置对应的参数。
  6. 前端发送请求,springboot将请求传递到前端控制器。通过这个URL路劲找到对应的映射注解标记的控制器方法,控制器去调用service层的方法执行业务逻辑。控制器返回视图给前端控制器,前端控制器调用视图解析器,解析视图返回给服务器,服务器将数据响应到客户端。

springboot打成的jar包和普通项目打成的jar包有什么区别

  1. springBoot :
    1. 内置了tomcat、jetty 的服务器,jar包可以单独运行。
    2. 将所有的依赖都打成一个jar包,当部署项目时,只需要一个jar包就可以运行。
    3. 简单的运行jar包命令-java - jar .jar 便可以启动。
    4. 在运行时,会自动根据配置文件自动配置组件。
相关推荐
不是只有你能在乱世中成为大家的救世主43 分钟前
学习第六十四行
linux·c语言·开发语言·经验分享·学习
JoneMaster2 小时前
[读书日志]从零开始学习Chisel 第十一篇:Scala的类型参数化(敏捷硬件开发语言Chisel与数字系统设计)
开发语言·学习·scala
一决威严-雪雪2 小时前
springboot整合admin
java·spring boot·后端
栗筝i2 小时前
Spring 中的常用注解
java·后端·spring
power-辰南2 小时前
人工智能学习路线全链路解析
人工智能·学习·机器学习
一只码代码的章鱼2 小时前
go学习笔记
笔记·学习
Chrikk2 小时前
NCCL学习笔记-安装验证
笔记·学习
sysu633 小时前
73.矩阵置零 python
开发语言·数据结构·python·线性代数·leetcode·面试·矩阵
new6669993 小时前
Java实现命令模式
java·命令模式