第四篇:SSM框架(Spring、SpringMVC、Mybatis)

目录

一. Spring

1. 简单说一下Spring

2. IOC是怎么实现的 / Spring的Bean是如何加载的 / 生命周期是什么样的?

3. BeanFactory和ApplicationContext有什么区别?

4、ApplicationContext的实现类有哪些?

5. Spring中的单例Bean是线程安全的吗?Spring如何解决线程并发问题?

7. Autowired和Resource有什么区别?RequestMapping有什么作用?

8. SpringAOP了解吗?AOP有哪些实现方式?

9. 过滤器和拦截器有什么区别?

10. Spring是如何解决循环依赖问题的?

12. Spring是怎么扫描注解或者xml文件的?

13. 怎么自定义一个Spring注解?

14. 怎么用AOP实现一个日志拦截或者异常拦截?

15. Spring中的设计模式

二. SpringMVC

1. 描述一下SpringMVC的工作流程

三. Mybatis

1. 为什么要使用Mybatis?

2. Mybatis原理?

3. #{} 和 ${} 有什么区别?

4. Mybatis的映射文件中如何遍历?

5. mapper接口是怎么找到mapper.xml中对应的sql的?

6. Mybatis一级缓存和二级缓存?

7. Mybatis get()和load()的区别?


一. Spring

1. 简单说一下Spring

Spring是一个轻量级java开发框架,简化了java开发。Spring有两大核心,IOC和AOP。

  • IOC是控制反转,把对象交给Spring来管理。IOC支持依赖注入(DI),可以动态的给一个对象注入它需要依赖的对象。
  • AOP是面向切面编程,横向抽取公共逻辑,封装成模块。可用于权限控制,日志处理等。

2. IOC是怎么实现的 / Spring的Bean是如何加载的 / 生命周期是什么样的?

Spring会先扫描xml文件或者注解拿到所有的beanDefination,然后把beanDefination放到map中,然后当调用的getBean方法的时候,先用beanDefination中的bean定义用反射的方式实例化bean,然后再进行属性注入,最后进行初始化(给属性赋值),再把bean放入ConcurrentHashMap中,整个就完成了bean的加载。我们使用的时候,就能直接从容器里获取bean了,所以IOC容器其实可以说是一个map。

第四篇:SSM框架(Spring、SpringMVC、Mybatis)_第1张图片

3. BeanFactory和ApplicationContext有什么区别?

BeanFactory和ApplicationContext都可以作为Spring的容器,BeanFactory是最底层的接口,ApplicationContext是BeanFactory的派生。BeanFactory是延迟加载,使用时才会加载,如果Bean的某一个属性没有注入,只有第一次使用时才出抛出异常。ApplicationContext在容器启动时,就会全部加载所有的Bean,虽然有些耗费内存,但是需要使用时无需等待。

4、ApplicationContext的实现类有哪些?

  • FileSystemXmlApplicationContext:此容器用xml的方式加载beans定义,需提供xml文件绝对路径
  • ClassPathXmlApplicationContext:此容器用xml的方式加载beans定义,需提供classpath和相对路径
  • WebXmlApplicationContext:此容器加载一个Xml文件,该文件定义了WEB应用的所有Bean
  • AnnotationConfigApplicationContext:用注解的方式启动容器

5. Spring中的单例Bean是线程安全的吗?Spring如何解决线程并发问题?

不安全,但是大多数Bean都是无状态的,也就是不存储数据,所以某种程度上说不存在线程安全问题。

对于需要存储数据的Bean,我们可以把共享变量设为ThreadLocal变量,那么访问这个变量的每个线程都会有一个变量副本,实际操作的时候,也是使用的本地变量副本,从而规避了线程安全问题。

7. Autowired和Resource有什么区别?RequestMapping有什么作用?

Autowired是按类型装配,Resource是按名称装配,名称不存在时按类型装配。RequestMapping用来映射URL。

8. SpringAOP了解吗?AOP有哪些实现方式?

SpringAOP是通过代理模式来实现的。代理模式分为静态代理和动态代理。

  • AspectJ就是静态代理,静态代理是在编译时期就把通知织入字节码文件中,运行的直接是增强后的字节码对象。
  • SpringAOP是动态代理,是在运行时动态的生成一个AOP对象,这个对象包含了被代理对象的全部方法,并且在特定切点做了增强处理,并回调原对象的方法。

Spring动态代理主要有2中实现方式,JDK动态代理和CGLIB动态代理。

  • JDK动态代理只能代理接口,不能代理类。实现方式:代理对象实现InvocationHandler,把被代理对象的接口从构造函数传入,然后用invoke接口实现增强,利用反射调用原对象里的方法。使用的时候,使用Proxy.newProxyInstatnce(代理类类加载器,被代理接口,被代理实现类)生成代理类,就可以调用方法了。
  • CGLIB可以代理类,主要是通过继承的方式来实现。实现方式:代理对象实现MethodInterceptor,对方法进行拦截处理。使用的时候,使用Enhance的setSuperClass(被代理类),setCallBack(代理类),最后用Enhance的create()来创建被代理类,就可以直接使用被代理类调用方法了。

9. 过滤器和拦截器有什么区别?

  • 实现原理上,过滤器是用回调实现的,拦截器是用动态代理实现的;
  • 使用范围上,过滤器必须实现java.servlet.filter接口,必须依赖tomcat等容器,拦截器在Spring包下,由Spring管理;
  • 触发时机上,过滤器在servlet前后执行,拦截器在controller前后执行;
  • 应用场景上,过滤器用于拦截非法参数,无效请求,拦截器用于权限校验,日志记录。

10. Spring是如何解决循环依赖问题的?

构造器注入的循环依赖是没有办法解决的,Spring解决了属性注入方式的循环依赖问题。比如A依赖B,B又依赖A,Spring会先在三级缓存中获取A是否存在,此时A肯定不存在,于是初始化A(因为B是以@Autowired注入的,所以此时并不会出发初始化B),并把A放入三级缓存中,然后进行populateBean(属性注入),此时初始化B,三级缓存中B也不存在,于是初始化B并放入三级缓存,再进行属性注入,此时三级缓存中有A,拿到A进行属性注入。

为什么要有三级缓存?两级不行吗?

Spring 的循环依赖:真的必须非要三级缓存吗?_Java知音_的博客-CSDN博客

  • 第一级缓存存的是对外暴露的对象,也就是我们应用需要用到的
  • 第二级缓存的作用是为了处理循环依赖的对象创建问题,里面存的是半成品对象或半成品对象的代理对象
  • 第三级缓存的作用处理存在 AOP + 循环依赖的对象创建问题,能将代理对象提前创建

12. Spring是怎么扫描注解或者xml文件的?

根据@ComponentScan配置的扫描路径,扫描这个路径下的注解,比如@Controller@Service@Repository@Component等,然后用反射的方式实例化被注解的类,并放入容器中。

13. 怎么自定义一个Spring注解?

定义注解就用@interface自定义一个注解,上边再加上一些元注解,比如@Target、@Retention、@Documented、@Inherited

元注解:

  • @Target表示注解的使用范围,包括类、方法、属性;
  • @Retention表示被它注解的注解类注解到别的类上时,可以保留到何时,包括源文件,编译器,运行时;
  • @Documented表示生成文档时是否要保留注解信息;
  • @Inherited注解表示被@Inherited注解的注解被注解到其他类上时,其子类自动可以拥有该注解。

14. 怎么用AOP实现一个日志拦截或者异常拦截?

有两种方式,一种是用切点的方式,一种是注解的方式。

切点的方式就是在@PointCut后边配置类路径,这个类路径下的所有方法都会被增强。

注解的方式就是在@Around@Before这种注解后边配置一个注解,所有被注解的类都会被增强。

方式一:切点方式

第四篇:SSM框架(Spring、SpringMVC、Mybatis)_第2张图片

用@Aspect注解的类就是一个切面,@Pointcut是一个切点,切点后边配置的是类路径,这个路径中所有方法都会被增强,@Around就是增强,joinPoint可以拿到所有切点中的方法,然后在切点前后做一些操作

方式二:注解的方式

第四篇:SSM框架(Spring、SpringMVC、Mybatis)_第3张图片

这里表示被@EnableTimerLog注解的所有类都会走到这个@Around注解的增强里,然后就可以在joinPoint.proceed()前后做处理。

15. Spring中的设计模式

  • 单例设计模式 : Spring 中的 Bean 默认都是单例的。
  • ⼯⼚设计模式 : Spring使⽤⼯⼚模式通过 BeanFactory 、 ApplicationContext 创建bean 对象。
  • 代理设计模式 : Spring AOP 功能的实现。
  • 观察者模式: Spring 事件驱动模型就是观察者模式很经典的⼀个应⽤。
  • 适配器模式:Spring AOP 的增强或通知(Advice)使⽤到了适配器模式、spring MVC 中也是⽤到了适配器模式适配 Controller 。

二. SpringMVC

1. 描述一下SpringMVC的工作流程

  • 用户发送一条请求到DispatcherServlet(控制器),DispatcherServlet访问HandleMapping(处理器映射器),获得Handler;
  • DispatcherServlet拿着Handler调用HandlerAdapter(处理器适配器),HandlerAdapter寻找合适的Handler执行业务逻辑,并返回ModelAndView;
  • DispatcherServlet拿着ModelAndView访问viewResolever(视图解析器),viewResolever解析完视图并返回给DispatcherServlet;
  • DispatcherServlet再请求视图进行渲染,最终给用户返回视图。

三. Mybatis

1. 为什么要使用Mybatis?

  • 使用Mybatis不用再手动创建连接,只需把数据库连接信息配置到配置文件中,Mybatis会创建连接池去连接数据库
  • 把sql语句和java代码隔离开了,改动sql也不影响java代码
  • Mybatis比hibernate更轻量,开发者也不用专门再去学HQL

Mybatis:轻量级框架,学习成本低,适合需求频繁变动的项目,需求变动只需改sql语句

Hibernate:重量级框架,需要学习HQL,适合需求不怎么变动的项目,需求变动需要改java代码

2. Mybatis原理?

  • 把配置文件中的数据库连接信息注入到DataSource中
  • 生成一个SqlSessionFactory,把DataSource注入到SqlSessionFactory的dataSource属性中,并把xml映射文件的路径注入到mapperLocation中
  • 创建sqlSession对象,执行sql语句,并把结果映射成java对象

MyBatis是如何把sql执行结果映射成对象的?

通过标签,里边映射属性 和列名

3. #{} 和 ${} 有什么区别?

#{} 和 ${} 都可以传入变量值,如#{userName}。

区别是变量替换后,#{} 会给变量自动加上' '单引号,但${} 不会。因此#{} 可以防止sql注入,${}不行。

4. Mybatis的映射文件中如何遍历?


         #{status}

5. mapper接口是怎么找到mapper.xml中对应的sql的?

Mapper.xml文件中的namespace即是mapper接口的类路径,xml中sql语句的id和接口中的方法名一致。

6. Mybatis一级缓存和二级缓存?

讲解:MyBatis 一级缓存、二级缓存_chy1984的博客-CSDN博客

一级缓存是sqlSession缓存,二级缓存是sqlSessionFactory缓存。

Mybatis的缓存作用是:如果要查询的内容在缓存中存在,则直接从缓存中取,否则查询数据库。

一级缓存默认开启,二级缓存默认关闭,因为缓存时间长,容易出现脏读问题,所以一般不用

##一级缓存的生命周期在sqlSession的生命周期之内,即在mapper方法调用的生命周期之内。

//一个sqlSession,open-> close,方法调用结束时一级缓存会被清空
userMapper.findUserByName();

//一个新的sqlSession
userMapper.findUserByName();

7. Mybatis get()和load()的区别?

get和load都会先从一级缓存和二级缓存中查找,区别是load是懒加载,需要的时候才去数据库查询。

你可能感兴趣的:(肖哈哈java自学笔记,mybatis,spring,java)