SpringMVC、Spring、Mybatis杂谈

1、Spring MVC

Spring MVC的处理流程

  • Web 容器启动时会通知 Spring 初始化容器,加载 Bean 的定义信息并初始化所有单例 Bean,然后遍历容器中的 Bean,获取每一个 Controller 中的所有方法访问的 URL,将 URL 和对应的 Controller 保存到一个 Map 集合中。
  • 所有的请求会转发给 DispatcherServlet 前端处理器处理
  • DispatcherServlet 会请求 HandlerMapping 找出容器中被 @Controler 注解修饰的 Bean 以及被 @RequestMapping 修饰的方法和类,生成 Handler 和 HandlerInterceptor 并以一个 HandlerExcutionChain 处理器执行链的形式返回。
  • 之后 DispatcherServlet 使用 Handler 找到对应的 HandlerApapter通过 HandlerApapter 调用 Handler 的方法,将请求参数绑定到方法的形参上,执行方法处理请求并得到 ModelAndView。
  • 最后 DispatcherServlet 根据使用 ViewResolver 试图解析器对得到的 ModelAndView 逻辑视图进行解析得到 View 物理视图,然后对视图渲染,将数据填充到视图中并返回给客户端。
  • 转

Spring MVC 有哪些组件

  • DispatcherServlet:SpringMVC 中的前端控制器,是整个流程控制的核心,负责接收请求并转发给对应的处理组件。
  • Handler:处理器,完成具体业务逻辑,相当于 Servlet 或 Action。
  • HandlerMapping:完成 URL 到 Controller 映射,DispatcherServlet 通过 HandlerMapping 将不同请求映射到不同 Handler。
  • HandlerInterceptor:处理器拦截器,是一个接口,如果需要完成一些拦截处理,可以实现该接口。
  • HandlerExecutionChain:处理器执行链,包括两部分内容:Handler 和 HandlerInterceptor。
  • HandlerAdapter:处理器适配器,Handler执行业务方法前需要进行一系列操作,包括表单数据验证、数据类型转换、将表单数据封装到JavaBean等,这些操作都由 HandlerAdapter 完成。DispatcherServlet 通过 HandlerAdapter 来执行不同的 Handler。
  • ModelAndView:装载模型数据和视图信息,作为 Handler 处理结果返回给 DispatcherServlet。
  • ViewResolver:视图解析器,DispatcherServlet 通过它将逻辑视图解析为物理视图,最终将渲染的结果响应给客户端。

Spring MVC 的相关注解

  • @Controller
  • @RequestMapping
  • @ModelAttribute和@SessionAttributes (传递和保存数据)
  • @PathVariable (路径参数)
  • @RequestParam

2、Spring

AOP

AOP是什么?

  • 面向切面编程:将代码中重复的部分抽取出来,在需要执行的时候使用动态代理技术,在不修改源码的基础上对方法进行增强。
  • Spring 根据类是否实现接口来判断动态代理方式
    • 如果实现接口会使用 JDK 的动态代理,核心是 InvocationHandler 接口和 Proxy 类;
    • 如果没有实现接口会使用 CGLib 动态代理CGLib 是在运行时动态生成某个类的子类
    • 如果某个类被标记为 final,不能使用 CGLib 。
  • JDK 动态代理主要通过重组字节码实现,首先获得被代理对象的引用和所有接口,生成新的类必须实现被代理类的所有接口,动态生成Java 代码后编译新生成的 .class 文件并重新加载到 JVM 运行。
  • JDK 代理直接写 Class 字节码,CGLib 是采用 ASM 框架写字节码,生成代理类的效率低。
  • 但是 CGLib 调用方法的效率高,因为 JDK 使用反射调用方法,CGLib 使用 FastClass 机制为代理类和被代理类各生成一个类,这个类会为代理类或被代理类的方法生成一个 index,这个 index 可以作为参数直接定位要调用的方法。

AOP相关注解

  • 标注切面类的注解(在一个标注了 Component 的类上用于标注该类是个切面类):@Aspect
  • (将被标注的方法织入到切点对应的连接点):@Before、@Around、@AfterReturning、@AfterThrowing、@After
  • 标注切点@Pointcut
  • 表示织入顺序@Order

AOP相关术语

  • Aspect:切面,一个关注点的模块化,这个关注点可能会横切多个对象。
  • Joinpoint:连接点,程序执行过程中的某一行为,即业务层中的所有方法。。
  • Advice:通知,指切面对于某个连接点所产生的动作,包括前置通知、后置通知、返回后通知、异常通知和环绕通知。
  • Pointcut:切入点,指被拦截的连接点,切入点一定是连接点,但连接点不一定是切入点。
  • Proxy:代理,Spring AOP 中有 JDK 动态代理和 CGLib 代理,目标对象实现了接口时采用 JDK 动态代理,反之采用 CGLib 代理。
  • Target:代理的目标对象,指一个或多个切面所通知的对象。
  • Weaving :织入,指把增强应用到目标对象来创建代理对象的过程。

AOP的过程

  • Spring AOP 由 BeanPostProcessor 后置处理器开始,这个后置处理器是一个***,可以监听容器触发的 Bean 生命周期事件,向容器注册后置处理器以后,容器中管理的 Bean 就具备了接收 IoC 容器回调事件的能力。BeanPostProcessor 的调用发生在 Spring IoC 容器完成 Bean 实例对象的创建和属性的依赖注入后,为 Bean 对象添加后置处理器的入口是 initializeBean 方法。
  • Spring 中 JDK 动态代理通过 JdkDynamicAopProxy 调用 Proxy 的 newInstance 方法来生成代理类,JdkDynamicAopProxy 也实现了 InvocationHandler 接口,invoke 方法的具体逻辑是先获取应用到此方法上的拦截器链,如果有拦截器则创建 MethodInvocation 并调用其 proceed 方法,否则直接反射调用目标方法。因此 Spring AOP 对目标对象的增强是通过拦截器实现的。

IOC

IOC是什么?

  • 控制反转:把原来代码里需要实现的对象创建、依赖反转给容器来帮忙实现,需要创建一个容器并且需要一种描述让容器知道要创建的对象间的关系,在 Spring 中管理对象及其依赖关系是通过 Spring 的 IoC 容器实现的。
  • IoC 的实现方式有依赖注入和依赖查找,由于依赖查找使用的很少,因此 IoC 也叫做依赖注入
  • 依赖注入指对象被动地接受依赖类而不用自己主动去找,**对象不是从容器中查找它依赖的类,而是在容器实例化对象时主动将它依赖的类注入给它。**假设一个 Car 类需要一个 Engine 的对象,那么一般需要需要手动 new 一个 Engine,利用 IoC 就只需要定义一个私有的 Engine 类型的成员变量,容器会在运行时自动创建一个 Engine 的实例对象并将引用自动注入给成员变量。

IoC 容器初始化过程?

  • 基于注解的容器初始化:
    • 直接将注解 Bean 注册到容器中,可以在初始化容器时注册,也可以在容器创建之后手动注册,然后刷新容器使其对注册的注解 Bean 进行处理。
    • 通过扫描指定的包及其子包的所有类处理,在初始化注解容器时指定要自动扫描的路径。

依赖注入的实现方式?

  • 构造方法
  • set方法注入
  • 接口注入

依赖注入的相关注解?

  • @Autowired
  • @Qualifier : 在Controller中需要注入service那么我的这个server有两个实现类如何区分开这两个impl,通过Qualifier 和Autowired;
  • @Resource
  • @Value

依赖注入的过程?

  • getBean 方法获取 Bean 实例,该方法调用 doGetBeandoGetBean 真正实现从 IoC 容器获取 Bean 的功能,也是触发依赖注入的地方。
  • 体创建 Bean 对象的过程由 ObjectFactory 的 createBean 完成,该方法主要通过 createBeanInstance 方法生成 Bean 包含的 Java 对象实例populateBean 方法对 Bean 属性的依赖注入进行处理
  • 在 populateBean方法中,注入过程主要分为两种情况:
    • 属性值类型不需要强制转换时,不需要解析属性值,直接进行依赖注入
    • 属性值类型需要强制转换时,首先解析属性值,然后对解析后的属性值进行依赖注入。依赖注入的过程就是将 Bean 对象实例设置到它所依赖的 Bean 对象属性上,真正的依赖注入是通过 setPropertyValues 方法实现的,该方法使用了委派模式。
  • BeanWrapperImpl 类负责对完成初始化的 Bean 对象进行依赖注入,对于非集合类型属性,使用 JDK 反射,通过属性的 setter 方法为属性设置注入后的值。对于集合类型的属性,将属性值解析为目标类型的集合后直接赋值给属性。
  • 当容器对 Bean 的定位、载入、解析和依赖注入全部完成后就不再需要手动创建对象,IoC 容器会自动为我们创建对象并且注入依赖。

Bean的生命周期?

  • 实例化 Instantiation
  • 属性赋值 Populate
  • 初始化 Initialization
  • 销毁 Destruction
  • XML 方式通过配置 bean 标签中的 init-Method 和 destory-Method 指定自定义初始化和销毁方法。
  • 注解方式通过 @PreConstruct 和 @PostConstruct 注解指定自定义初始化和销毁方法。

Bean的作用范围?

  • 通过 scope 属性指定 bean 的作用范围,包括:
    • singleton单例模式,是默认作用域,不管收到多少 Bean 请求每个容器中只有一个唯一的 Bean 实例。
    • prototype原型模式,和 singleton 相反,每次 Bean 请求都会创建一个新的实例
    • request每次 HTTP 请求都会创建一个新的 Bean 并把它放到 request 域中,在请求完成后 Bean 会失效并被垃圾收集器回收。
    • session:和 request 类似,确保每个 session 中有一个 Bean 实例,session 过期后 bean 会随之失效。
    • global session:当应用部署在 Portlet 容器时,如果想让所有 Portlet 共用全局存储变量,那么该变量需要存储在 global session 中。

通过注解创建Bean

  • @Component 把当前类对象存入 Spring 容器中,相当于在 xml 中配置一个 bean 标签。value 属性指定 bean 的 id,默认使用当前类的首字母小写的类名。
  • @Controller,@Service,@Repository 三个注解都是 @Component 的衍生注解,作用及属性都是一模一样的。只是提供了更加明确语义,@Controller 用于表现层,@Service用于业务层,@Repository用于持久层。如果注解中有且只有一个 value 属性要赋值时可以省略 value。
  • 如果想将第三方的类变成组件又没有源代码,也就没办法使用 @Component 进行自动配置,这种时候就要使用 @Bean 注解。被 @Bean 注解的方法返回值是一个对象,将会实例化,配置和初始化一个新对象并返回,这个对象由 Spring 的 IoC 容器管理。name 属性用于给当前 @Bean 注解方法创建的对象指定一个名称,即 bean 的 id。当使用注解配置方法时,如果方法有参数,Spring 会去容器查找是否有可用 bean对象,查找方式和 @Autowired 一样。

如何通过注解配置文件

  • @Configuration 用于指定当前类是一个 spring 配置类,当创建容器时会从该类上加载注解,value 属性用于指定配置类的字节码。
  • @ComponentScan 用于指定 Spring 在初始化容器时要扫描的包。basePackages 属性用于指定要扫描的包。
  • @PropertySource 用于加载 .properties 文件中的配置。value 属性用于指定文件位置,如果是在类路径下需要加上 classpath。
  • @Import 用于导入其他配置类,在引入其他配置类时可以不用再写 @Configuration 注解。有 @Import 的是父配置类,引入的是子配置类。value 属性用于指定其他配置类的字节码。

BeanFactory、FactoryBean 和 ApplicationContext 的区别?

  • BeanFactory 是一个 Bean 工厂,使用简单工厂模式,是 Spring IoC 容器顶级接口,可以理解为含有 Bean 集合的工厂类,作用是管理 Bean,包括实例化、定位、配置对象及建立这些对象间的依赖。BeanFactory 实例化后并不会自动实例化 Bean,只有当 Bean 被使用时才实例化与装配依赖关系,属于延迟加载,适合多例模式。
  • FactoryBean 是一个工厂 Bean,使用了工厂方法模式,作用是生产其他 Bean 实例,可以通过实现该接口,提供一个工厂方法来自定义实例化 Bean 的逻辑。FactoryBean 接口由 BeanFactory 中配置的对象实现,这些对象本身就是用于创建对象的工厂,如果一个 Bean 实现了这个接口,那么它就是创建对象的工厂 Bean,而不是 Bean 实例本身。
  • **ApplicationConext 是 BeanFactory 的子接口,扩展了 BeanFactory 的功能,**提供了支持国际化的文本消息,统一的资源文件读取方式,事件传播以及应用层的特别配置等。容器会在初始化时对配置的 Bean 进行预实例化,Bean 的依赖注入在容器初始化时就已经完成,属于立即加载,适合单例模式,一般推荐使用。

3、Mybatis

Mybatis 的优缺点?

优点

  • SQL写在XML配置文件中,便于统一管理;
  • 提供了很多插件(分页插件/逆向工程),并与Spring有很好的集成;
  • 提供XML,支持动态SQL
  • 提供映射标签,支持对象与数据库的ORM字段关系映射。
  • 提供对象关系映射标签,支持对象关系组建维护。

缺点

  • SQL编写量巨大
  • SQL依赖于数据库

Mybatis 的 XML 文件有哪些标签属性?

(转) XML标签属性

Mybatis的一级缓存

  • 一级缓存是 SqlSession 级别,默认开启且不能关闭
  • 操作数据库时需要创建 SqlSession 对象,对象中有一个 HashMap 存储缓存数据,不同 SqlSession 之间缓存数据区域互不影响。
  • 一级缓存的作用域是 SqlSession 范围的,在同一个 SqlSession 中执行两次相同的 SQL 语句时,第一次执行完毕会将结果保存在缓存中,第二次查询直接从缓存中获取。
  • 如果 SqlSession 执行了 DML 操作(insert、update、delete),Mybatis 必须将缓存清空保证数据有效性
  • 屏蔽一级缓存,flushCache="true"

(转)一级缓存详解

Mybatis的二级缓存

  • 二级缓存是Mapper 级别,默认关闭
  • 使用二级缓存时多个 SqlSession 使用同一个 Mapper 的 SQL 语句操作数据库,得到的数据会存在二级缓存区,同样使用 HashMap 进行数据存储,相比于一级缓存,二级缓存范围更大,多个 SqlSession 可以共用二级缓存,作用域是 Mapper 的同一个 namespace,不同 SqlSession 两次执行相同的 namespace 下的 SQL 语句,参数也相等,则第一次执行成功后会将数据保存在二级缓存中,第二次可直接从二级缓存中取出数据。
  • 要使用二级缓存,需要在全局配置文件中配置 <setting name=“cacheEnabled” value=“true”/> ,再在对应的映射文件中配置一个 标签
  • 使用二级缓存意味着:
    • 映射语句文件中的所有select语句将会被缓存。
    • 映射语句文件中的所有insert、update和delete语句会刷新缓存。
    • 缓存会使用默认的Least Recently Used(LRU,最近最少使用的)算法来收回。
    • 根据时间表,比如No Flush Interval,(CNFI没有刷新间隔),缓存不会以任何时间顺序来刷新。
    • 缓存会存储列表集合或对象(无论查询方法返回什么)的1024个引用
    • 缓存会被视为是read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以安全的被调用者修改,不干扰其他调用者或线程所做的潜在修改

(转)Cache

#{}和${}

  • #{} :
    • 占位符;
    • sql 预编译;
    • 变量替换后,#{} 对应的变量自动加上单引号 ‘’
    • #{} 能防止sql 注入
  • ${}:
    • 拼接符;
    • sql拼接;
    • 变量替换后,${} 对应的变量不会加上单引号 ‘’
    • ${} 不能防止sql 注入

参考:
https://www.zhihu.com/question/53673888/answer/2013711983

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值