Spring框架

Spring框架

什么是Spring框架

Spring是一种轻量级的开发框架,旨在提高开发人员的开发效率以及系统的可维护性。我们一般说的是Spring框架 指的是Spring Framework,它是很多模块的磨合,使用这些模块可以很方便地协助我们进行开发。这些模块是:核心容器、数据访问/集成,Web,AOP(面向切面编程)、工具、消息和测试模块。比如:Core Container中的Core组件是Spring所有组件的核心,Beans组件和Context组件时实现IOC和依赖注入的基础,AOP组件用来实现面向页面编程。

Spring官网列出的Spring的六个特征:

  • 核心技术:依赖注入(IOC),AOP(面向切面编程),事件(events),资源,i18n、验证、数据绑定、类型转换、spEL。
  • 测试:模拟对象,TestContext框架、SpringMVC测试、WebTestClient
  • 数据访问:事务、DAO支持、JDBC、ORM、编组XML。
  • Web支持:Spring MVC和Spring webFlux Web框架。
  • 集成:远程处理、JMS、JCA、JMX、电子邮件、任务、调度、缓存。
  • 语言:Kotlin、Groovy、动态语言。

列举一些重要的Spring模块

  • spring Core:基础,可以说spring所有功能都需要依赖于该库。主要提供Ioc依赖注入功能。
  • Spring Aspects:该模块为与AspectJ的集成提供支持;
  • Spring AOP:提供了面向切面的编程实现;
  • Spring JDBC:Java数据库连接;
  • Spring JMS:Java消息服务
  • Spring ORM:用于支持Hibernate等ORM操作;
  • Spring Web:为 创建Web应用程序提供支持。
  • Spring Test:提供了对JUnit和TestNG测试的支持。

@RestController vs@Controller

@Controller返回一个页面

单独使用@Controller不加@ResponseBody的话 一般使用在要返回一个视图的情况,这种情况属于比较传统的Spring MVC应用,对应于前后端不分离的情况。

@RestController返回JSON或XML形式数据

但@RestController只返回对象对象,对象数据直接以JSON或XML形式写入HTTP响应中。这种情况属于Restful Web服务,这也是目前日常开发所接触的最常用的情况(前后端分离)。

@Controller+@ResponseBody返回JSON或XML形式数据

如果你需要在Spring4之前开发RESTful Web服务的话,你需要使用@Controller,并结合@ResponseBody注解。

@ResponseBody注解的作用是将Controller的方法返回的对象通适当的转换器转换为指定的格式之后,写入到HTTP响应 (Response)对象的Body中,通常用来返回JSON或者XML数据,返回JSON数据的情况比较多。

Spring IOC&AOP

IOC

IOC(Inverse of Controller:控制反转)是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。IOC在其他语言中也有应用,并非Spring特有。IOC容器是Spring用来实现IOC的载体,IOC容器实际上就是Map(key,value),map存放的是各种对象。

将对象之间的相互依赖关系交给IOC容器来管理,并由IOC容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。IOC容器 就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置号文件/注解即可,完全不用 考虑对象是如何被创建出来的。在实际项目中一个Service类可能有几百个甚至上千个类 作为它的底层,加入 我们需要实例化这个Service,你可能每次都要搞清这个Service所有底层类的构造函数,这可能会把人逼疯。如果利用IOC的话,你只需要配置好,然后在需要的地方引用 就好了,这大大增加了项目 的可维护性 并且降低了开发难度。

Spring时代我们一般通过XML文件来配置Bean,后来开发人员觉得XML文件来配置不太好 ,于是SpringBoot注解 配置就慢慢开始流行起来。

Spring IOC的初始化过程:

XML——>读取 Resource——>解析 BeanDefinition ——>注册——>BeanFactory

AOP

AOP(Aspect—Oriented Programming:面向切面编程 )能够将那些与业务无关,却为业务模块所共同调用的逻辑和责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

Spring AOP就是基于动态代理的,如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用JDK proxy去进行代理了,这时候Spring AOP会使用Cglib,这时候Spring AOP会使用Cglib生成一个代理对象的子类来作为代理。

当然也可以使用AspectJ,Spring AOP已经集成了AspectJ,AspectJ应该算的上是Java生态系统中最完整的AOP框架了。

使用AOP之后我们可以把一些通用功能抽象出来,在需要用的到的地方直接使用即可,这样大大简化了代码量。我们需要增加新功能时也方便,这样也提高了系统扩展性。日志功能、事务管理等等场景都用了AOP。

Spring AOP和AspectJ AOP有什么区别

Spring AOP属于运行时增强,而AspectJ是编译时增强。Spring AOP基于代理(Proxying),而AspectJ基于字节码操作(Bytecode Manipulation)

Spring AOP已经集成了AspectJ,AspectJ应该算得上是java生态系统中最完整的AOP框架了,AspectJ相比于SpringAOP功能更加强大,但是Spring AOP相对来说更简单。

如果我们的切面比较少,那么两者性能相差不大。但是,当切面太多的话,最好选择AspectJ,它比Spring AOP快很多。

Spring bean

Spring中的bean的作用域有哪些?

  • singleton:唯一bean实例,Spring中 的bean默认都是单例的。
  • prototype:每次请求都会创建一个新的bean实例;
  • request:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效;
  • session:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP session内有效;
  • global-session:全局session作用域,仅仅在基于portlet的web应用中才有意义,Spring5已经 没有了。Portlet是 能够生成语义代码(例如HTML)片段的小型Java Web插件,它们基于portlet容器,可以像servlet一样处理HTTP请求。但是,与Servlet不同,每个portlet都有不同的会话。

Spring中的单例bean的线程安全问题了解吗?

大部分时候我们并没有 在系统中使用多线程,所以很少有人会关注这个问题。单例bean存在线程问题,主要是因为当多个线程操作同一个对象的时候,对这个对象的的非静态成员变量的写操作会存在线程安全问题。

常见的有两种解决办法:

  1. 在Bean对象中尽量避免定义可变的成员变量(不太现实)
  2. 在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在ThreadLocal中(推荐的一种方式)

@Component和@Bean的区别是什么?

  1. 作用对象不同,@Component注解作用于类,而@Bean注解作用于方法。
  2. @Component通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中(我们可以使用@ComponentScan注解定义要扫描的路径从中找出表示了需要装配的类自动装配到Spring 的Bean容器中 )。@Bean注解通常是我们在标有该注解的方法中定义产生这个bean,@Bean告诉了Spring这是某个类的实例,当我需要用它的时候还给我。
  3. @Bean注解比@Component注解自定义性更强,而且更多地方我们只能通过@Bean注解来注册bean,比如当我们引用第三方库中的类需要装配到Spring容器时,则只能 通过@Bean来实现。

@Bean注解使用示例:

@Configuration
public class AppConfig{
    @Bean
    public TransferService transferService(){
        return new TransferServiceImpl();
    }
}

上面的代码相当于下面的xml配置

<beans>
    <bean id="transferService" class="com.acme.TransferServiceImpl" />
</beans>

将一个类声明为Spring的bean的注解有哪些

我们一般使用@Autowired注解自动装配bean,要把类标识成可用于@Autowired注解自动装配 的bean的类,采用 以下注解可实现:

  • @Component:通用的注解,可标注任意类为 Spring组件。如果 一个Bean不知道属于哪个层,可以使用Component注解 标注;
  • @Repository:对应 持久层即Dao层,主要用于数据库相关操作;
  • @Service:对应服务层,主要 涉及一些复杂的逻辑,需要用到Dao层;
  • @Controller:对应 SpringMVC控制层,主要用于接受用户请求 并调用Service层返回数据 给前端页面。

说说你对SpringMVC的理解

谈到这个问题,我们不得不提之前Model1和 Model2这两个没有Spring MVC的时代 ;

  • Model1时代:很多学Java后端比较晚的朋友可能并没有接触过Model1模式下的JavaWeb应用开发。在 model2模式下,整个web应用 几乎全部用JSP页面组成,只用 少量的JavaBean来处理数据库连接、访问等操作。在这个模式下 ,JSP既是控制层又是 表现层,显而易见 ,这种模式存在很多问题。比如1.将逻辑控制和表现逻辑混杂在一起 ,导致代码重用率极低;2.前端和后端相互依赖,难以进行测试并且 开发效率极低。
  • Model2时代:学过Servlet并做过相关Demo的朋友应该了解“Java Bean(Model)+JSP+Servlet(Controller)”这种开发模式,这就是早期的JavaBean MVC开发模型。Model:系统涉及的数据,也就是dao和bean。view:展示模型中的数据,只是用来展示。Controller:处理用户请求,返回数据给JSP并展示给用户。

Model2模式下还存在很多问题,Model2的抽象和封装程度还远远不够,使用model2进行开发时不可避免地 会重复 造轮子,这就大大降低了程序地可维护性和复用性。于是很多JavaWeb开发相关的MVC框架应运而生比如Struct2,但是Structs2比较笨重。随着Spring轻量级开发框架的流行,Spring生态圈出现了Spring MVC框架,SpringMVC是当前最优秀的MVC框架。相比于Struts2,Spring MVC使用更加简单和方便,开发效率更高,并且Spring MVC运行速度更快。

MVC是一种设计模式,Spring MVC是一款很优秀的MVC框架。Spring MVC可以帮助我们进行更简洁的Web层的开发,并且它天生与Spring框架集成。Spring MVC下我们一般把后端项目分为Service层(处理业务)、Dao层(数据库操作)、Entity层(实体类)、Controller(控制层,返回数据给前台页面)。

Spring框架中用到了哪些涉及模式

  • 工厂设计模式:Spring使用工厂模式通过BeanFactory、ApplicationContext、创建bean对象。
  • 代理设计模式:Spring AOP功能的实现;
  • 单例设计模式:Spring中的Bean默认都是单例的;
  • 包装器设计模式:我们的项目需要连接多个数据库,而且不同的客户在每次访问中会根据需要会去访问不同的数据库,这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
  • 观察者模式:Spring AOP的增强或通知(Advice)使用到了适配器模式,SpringMVC种也是用到了适配器模式适配Controller。

Spring管理事务的方式有几种

  1. 编程式事务:在代码种硬编码(不推荐使用)
  2. 声明式事务:在配置文件种配置(推荐使用)

声明式事务又分为 两种:

  1. 基于XML的声明式事务;
  2. 基于注解的声明式事务

Spring事务中的隔离级别有哪几种

TransactionDefinition接口中定义了五个表示隔离级别的常量:

  • TransactionDefinition.ISOLATION_DEFAULT:使用后端数据库默认的隔离界别,MySQL默认 采用的REPEATABLE_READ隔离级别,Oracle默认采用READ_COMMITTED的隔离级别。
  • TransactionDefinition.ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取尚未 提交的数据变更 ,可能会导致奔溃,幻读或者不可重复度。
  • TransactionDefinition.ISOLATION_READ_COMMITTED:允许读取并发事务已经提交的数据,可以组织脏读,但是幻读或 不可重复读仍有可能发生;
  • TransactionDefinition.ISOLATION_REPEATABLE_READ:对同一字段的多次 读取结果都是一致的,除非数据是被 本身事务自己所修改 ,可以阻止脏读和不可重复读,但是幻读 有可能发生。
  • TransactionDefinition.ISOLATION_SERIALIZABLE:最高的隔离级别,完全服从ACID 的隔离级别,所有事务一次 逐个进行 ,这样事务 之间就完全不可能 产生 干扰,也就是说,该级别可以防止脏读,不可重复度以及幻读 。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值