Spring的一些基本操作: 1、bean标签用于配置对象,让spring容器对该对象进行管理;bean标签中的property标签(对应set方法)或constructor-arg标签(对应有参构造方法)用于配置对象中的属性;当然也可以直接使用@bean标签将方法转配到Spring容器中。 2、直接将类注入到Spring容器:@Component、@Repository、@Service、@Controlle;同时@Autowired注解可以对类成员变量、方法及构造函数进行标注,让 spring 完成 bean 自动装配的工作。 1、Spring是针对bean的生命周期进行管理的轻量级容器,其核心功能为IOC和AOP 1)控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。IOC的思想就是将原本在程序中手动创建对象的控制权交给Spring框架管理。 IoC 容器实际上就是个 Map(key,value),Map 中存放的是各种对象。 Spring时代一般使用xml文件配置bean,后续随着SpringBoot的发展,使用注解配置就开始慢慢流行起来了 2)AOP(Aspect Oriented Programming):面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
2、声明一个Bean的注解有哪些? 1)@Component :通用的注解,可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用@Component 注解标注。 2)@Repository : 对应持久层即 Dao 层,主要用于数据库相关操作。 3)@Service : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。 4)@Controller : 对应 Spring MVC 控制层,主要用户接受用户请求并调用 Service 层返回数据给前端页面 @Component、@Repository、@Service、@Controlle这些注解的功能都是创建bean实例将类中对象注入到容器中,就不需要再xml中定义bean了
3、@Component 和 @Bean 的区别是什么? 1)@Component :通用的注解,可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用@Component 注解标注。 2)@Component通常是通过类路径扫描来自动侦测以及自动装配到 Spring 容器中(我们可以使用 @ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring 的 bean 容器中)。@Bean 注解通常是我们在标有该注解的方法中定义产生这个 bean,@Bean告诉了 Spring 这是某个类的实例,当我需要用它的时候还给我。。 3)@Bean 注解比 @Component 注解的自定义性更强,而且很多地方我们只能通过 @Bean 注解来注册 bean。比如当我们引用第三方库中的类需要装配到 Spring容器时,则只能通过 @Bean来实现。
4、@Autowired 和 @Resource 的区别是什么? 1)Autowired 属于 Spring 内置的注解,默认的注入方式为byType(根据类型进行匹配),也就是说会优先根据接口类型去匹配并注入 Bean (接口的实现类)。当一个接口有多个时间类时,要通过 @Qualifier 注解来定义注入的实现类。(由Spring提供的注解) 2)@Resource属于 JDK 提供的注解,默认注入方式为 byName。通过name属性指定注入对象,如果无法通过名称匹配到对应的 Bean 的话,注入方式会变为byType。(有JDK提供的注解) @Autowired和@Resource注解都可以实现属性注入
5、Bean的生命周期 Bean的生命周期指的是对象从创建到销毁的过程 1)Bean容器利用 Java Reflection API 创建创建bean实例 2)为bean的属性设置值和对其他bean的引用(调用set方法) 3)把bean实例传递给bean的前置处理器-postProcessBeforeInitialization() 4)调用bean的初始化的方法(需要进行配置初始化的方法) 5)把bean实例传递给bean的后置处理器-postProcessAfterInitialization() 6)bean可以使用了(对象可以获取到) 7)当容器关闭时,调用bean销毁方法 6、AOP底层使用动态代理方式有两种,基于接口的动态代理和基于子类的动态代理 有接口的情况下,使用JDK动态代理,创建接口实现类代理对象,增强类的方法;通过使用Proxy类里边的方法创建代理对象。1)创建接口,定义接口方法;2)创建接口方法将接口方法实现;3)使用Proxy创建接口代理对象 没有接口的情况,使用CGLIB动态代理,创建子类代理对象增强类的方法 jdk动态代理只能基于接口,代理生成的对象只能赋值给接口变量,而Cglib就不存在这个问题,Cglib是通过生成子类来实现的,代理对象既可以赋值给实现类,又可以赋值给接口。Cglib速度比jdk动态代理更快,性能更好 7、AOP术语 1、连接点:类里面哪些方法可以被增强,这些方法称为连接点 2、切入点:实际被真正增强的方法,称为切入点 3、通知(增强):实际增强的逻辑部分称为通知(增强),也即拦截到目标对象的连接点之后要做的事情 通知有多种类型:前置通知(增强方法前执行)、后置通知(增强方法后执行)、环绕通知(增强方法前后都会执行)、异常通知(增强方法出现异常会执行)、最终通知(finally) 4、切面:是动作,将通知应用到切入点(增强方法)过程,即切入点+通知 5、代理:向目标对象应用通知之后创建的代理对象
7、Spring AOP 和 AspectJ AOP 有什么区别? Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。 AspectJ:不是Spring组成部分,但一般把AspectJ和Spring框架一起使用,进行AOP操作 基于注解的AspectJ操作,使用@Aspect注解标注增强类生成代理对象,使用@Order(n)注解定义切面顺序,n越小优先级越高(多个切面顺序的控制方法)
8、SpringMVC有三层结构:模型层、视图层、控制层 1)模型层:专门用于存储业务逻辑和数据访问,负责在控制器和展现数据的视图之间传递数据。 2)视图层:指工程中的html或jsp等页面,作用是与用户交互,展现数据 3)控制层:指工程中的servlet,用于接收请求和响应浏览器(返回数据给JSP并展示个用户)
9、SpringMVC的核心组件 1)DispatcherServlet :核心的中央处理器,负责接收请求、分发,并给予客户端响应。 2)HandlerMapping :处理器映射器,根据 uri 去匹配查找能处理的 Handler ,并会将请求涉及到的拦截器和 Handler 一起封装。 3)HandlerAdapter :处理器适配器,根据 HandlerMapping 找到的 Handler ,适配执行对应的 Handler; 4)Handler :请求处理器,处理实际请求的处理器。 5)ViewResolver :视图解析器,根据 Handler 返回的逻辑视图 / 视图,解析并渲染真正的视图,并传递给 DispatcherServlet 响应客户端
10、SpringMVC工作原理 1)客户端(浏览器)发送请求, DispatcherServlet拦截请求。 2)DispatcherServlet 根据请求信息调用 HandlerMapping 。HandlerMapping 根据 uri 去匹配查找能处理的 Handler(也就是我们平常说的Controller 控制器) ,并会将请求涉及到的拦截器和 Handler 一起封装。 3)DispatcherServlet 调用 HandlerAdapter适配执行 Handler 。 4)Handler 完成对用户请求的处理后,会返回一个 ModelAndView 对象给DispatcherServlet,ModelAndView 顾名思义,包含了数据模型以及相应的视图的信息。Model 是返回的数据对象,View 是个逻辑上的 View。 5)ViewResolver 会根据逻辑 View 查找实际的 View。 6)DispaterServlet 把返回的 Model 传给 View(视图渲染)。 7)把 View 返回给请求者(浏览器) 另一种说法:用户在视图层发送请求给服务器;服务器中请求被控制层(Controller)接收;控制层调用模型层(Module)处理请求;请求处理完毕后返回控制层;控制层再根据请求处理结果找到相应的View视图,渲染数据后最终响应给浏览器。 11、统一异常处理怎么做? 使用@ControllerAdvice + @ExceptionHandler 这两个注解统一处理异常,这种异常处理方式下,会给所有或者指定的 Controller 织入异常处理的逻辑(AOP),当 Controller 中的方法抛出异常的时候,由被@ExceptionHandler 注解修饰的方法进行处理。 ExceptionHandlerMethodResolver 中 getMappedMethod 方法决定了异常具体被哪个被 @ExceptionHandler 注解修饰的方法处理异常。
12、Spring框架中使用了那些设计模式。 1)工厂模式:Spring使用工厂模式通过BeanFactory、ApplicationContext创建bean对象; 2)代理设计模式:Spring 中的AOP(面向切面编程)的功能实现是基于代理模式实现的。 3)单例模式:Spring中的Bean默认都是单例的 4)模板方法模式:Spring中的jdbcTemplate\hibernateTemplate等以Template结尾的对数据库操作的类使用到了模板模式; 5)观察者模式:Spring事件驱动模型就是观察者模式很经典的一个应用; 6)适配器模式:Spring的AOP中增强或通知使用到了适配器模式、SpringMVC中也是使用到了适配器模式适配Controller … …
13、Spring的两种事务方式:编程式事务(不推荐使用)和声明式事务 1)编程式事务:通过 TransactionTemplate或者 TransactionManager 手动管理事务,实际应用中很少使用,但是对于你理解 Spring 事务管理原理有帮助。(在代码中硬编码,不推荐使用) 2)在 XML 配置文件中配置或者直接基于注解(推荐使用) : 实际是通过 AOP 实现(基于@Transactional 的全注解方式使用最多)
14、Spring事务中有哪几种事务传播行为 1)TransactionDefinition.PROPAGATION_REQUIRED:使用@Transactional注解默认使用的就是这个事务传播行为。该行为表示如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。 2)TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新事务,如果当前事务存在,则把当前事务挂起。 3)TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。 4)TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)
15、Spring事务的隔离级别 1)TransactionDefinition.ISOLATION_READ_UNCOMMITTED 读未提交(READ_UNCOMMITTED):隔离级别最低,允许读取尚未提交的数据变更,从而导致脏读、幻读和不可重复读 2)TransactionDefinition.ISOLATION_READ_COMMITTED 读已提交(READ_COMMITED):允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读和不可重复读仍有可能发生。 3)TransactionDefinition.ISOLATION_REPEATABLE_READ 可重复读(REPEATALBE READ):对同一字段的多次读取结果是一致的,除非数据是被本身事务自己修改,可以阻止脏读和不可重复读,但幻读仍有可能法师。 4)TransactionDefinition.ISOLATION_SERIALIZABLE 串行化(SERIALIZABLE ):最高隔离级别,服从事务四大特性(ACID),可以有效防止脏读、幻读、不可重复读,但缺点是影响程序性能。
16、@Transactional(rollbackFor = Exception.class)注解 @Transactional当该注解作用于类上时,类中的所有public方法将具有该类型的事务属性,同时也可以在方法上进行标注实现对类级别定义的覆盖。在类或方法中添加了该注解,如果抛出了异常,就会回滚,数据库里面的数据也会回滚。 由于异常分为运行时异常和非运行时异常,若在@Transactional注解中没有配置rollbackFor 属性,那么事务只会在遇到运行时异常(RuntimeExecption)才会回滚,通过添加rollbackFor=Exception.class可以让事务在遇到非运行时异常也回滚
17、SpringBoot和Spring常用注解 1)@SpringBootApplication 该注解是Springboot项目的基石,会在创建Springboot项目后默认在主类加上。该注解可以看成是@Configuration、@EnableAutoConfiguration、@ComponentScan 注解的集合。其中 @EnableAutoConfiguration用于启动Springboot的自动配置机制;@ComponentScan:用于扫描被@Component (@Repository,@Service,@Controller)注解的 bean,注解默认会扫描该类所在的包下所有的类;@Configuration:允许在 Spring 上下文中注册额外的 bean 或导入其他配置类 2)@Autowired:用于自动导入对象到类中,被注入进的类同样要被Spring容器所管理。 3)@Component,@Repository,@Service, @Controller注解。我们一般使用 @Autowired 注解让 Spring 容器帮我们自动装配 bean。而想要使用@Autowired 注解自动装配的 bean 的类可以采用以下注解实现: @Component:通用注解,可以标注任意类为Spring组件。如果不知道Bean属于那一层,可以使用该注解标志 @Repository:将持久层(Dao)层中的类标注为Spring组件,主要用于数据库的相关操作; @Service:将服务层中的类标注为Spring组件,主要涉及复杂业务逻辑,需要用到Dao层; @Controller:将SpringMVC控制层的类添加到Spring容器,主要用于接受用户请求并调用 Service 层返回数据给前端页面。 4)@RestController注解可以看成是@Controller和@ResponseBody的合集,表示这是个控制层的Bean,并且是将函数的返回值直接填入到HTTP响应体中,是REST风格的控制器。单独使用 @Controller 不加 @ResponseBody的话一般是用在要返回一个视图的情况,这种情况属于比较传统的 Spring MVC 的应用,对应于前后端不分离的情况。@Controller +@ResponseBody 返回 JSON 或 XML 形式数据。 @Controller与@RestController:@Controller用于返回一个视图,应用与比较传统的SpringMVC,对应前后端不分离的情况;@RestController只返回对象,返回对象数据以JSON或XML形式数据写入HTTP响应中,常用于前后端分离。 5)@Scope注解用于声明Spring Bean的作用域,常见的作用域有四种: singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。 prototype : 每次请求都会创建一个新的 bean 实例。 request : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。 session : 每一个 HTTP Session 会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。 6)@Configuration注解:用于声明配置类,可以使用@Component注解代替,不过使用@Configuration注解声明配置类更加语义化 7)常见HTTP请求 GET :请求从服务器获取特定资源。举个例子:GET /users(获取所有学生) POST :在服务器上创建一个新的资源。举个例子:POST /users(创建学生) PUT :更新服务器上的资源(客户端提供更新后的整个资源)。举个例子:PUT /users/12(更新编号为 12 的学生) DELETE :从服务器删除特定的资源。举个例子:DELETE /users/12(删除编号为 12 的学生) PATCH :更新服务器上的资源(客户端提供更改的属性,可以看做作是部分更新),使用的比较少,这里就不举例子了。 @GetMapping注解:用于匹配GET请求,@GetMapping(“users”) 等价于@RequestMapping(value=“/users”,method=RequestMethod.GET) @PostMapping注解:用于匹配POST请求,@PostMapping(“users”) 等价于@RequestMapping(value=“/users”,method=RequestMethod.POST) @PutMapping注解:用于匹配PUT请求,@PutMapping(“/users/{userId}”) 等价于@RequestMapping(value=“/users/{userId}”,method=RequestMethod.PUT) @DeleteMapping注解:用于匹配DELETE请求,@DeleteMapping(“/users/{userId}”)等价于@RequestMapping(value=“/users/{userId}”,method=RequestMethod.DELETE) 8)前后端传值常用注解: @PathVariable 和 @RequestParam:@PathVariable用于获取路径参数,@RequestParam用于获取查询参数。 @RequestBody注解:用于读取 Request 请求(可能是 POST,PUT,DELETE,GET 请求)的 body 部分并且Content-Type 为 application/json 格式的数据,接收到数据之后会自动将数据绑定到 Java 对象上去。系统会使用HttpMessageConverter或者自定义的HttpMessageConverter将请求的 body 中的 json 字符串转换为 java 对象。 9)读取配置信息 @Value(常用):使用 @Value(“${property}”) 读取比较简单的配置信息; @ConfigurationProperties(常用):通过@ConfigurationProperties读取配置信息并与 bean 绑定,@ConfigurationProperties(prefix = “library”)。 10)参数校验:数据的校验的重要性就不用说了,即使在前端对数据进行校验的情况下,我们还是要对传入后端的数据再进行一遍校验,避免用户绕过浏览器直接通过一些 HTTP 工具直接向后端请求一些违法数据。JSR(Java Specification Requests) 是一套 JavaBean 参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们 JavaBean 的属性上面,这样就可以在需要校验的时候进行校验了。校验的时候我们实际用的是 Hibernate Validator 框架。Hibernate Validator 是 Hibernate 团队最初的数据校验框架,Hibernate Validator 4.x 是 Bean Validation 1.0(JSR 303)的参考实现,Hibernate Validator 5.x 是 Bean Validation 1.1(JSR 349)的参考实现,目前最新版的 Hibernate Validator 6.x 是 Bean Validation 2.0(JSR 380)的参考实现。 常用字段验证注解: @NotEmpty 被注释的字符串的不能为 null 也不能为空 @NotBlank 被注释的字符串非 null,并且必须包含一个非空白字符 @Null 被注释的元素必须为 null @NotNull 被注释的元素必须不为 null @AssertTrue 被注释的元素必须为 true @AssertFalse 被注释的元素必须为 false @Pattern(regex=,flag=)被注释的元素必须符合指定的正则表达式 @Email 被注释的元素必须是 Email 格式。 @Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值 @Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值 @DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值 @DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 @Size(max=, min=)被注释的元素的大小必须在指定的范围内 @Digits(integer, fraction)被注释的元素必须是一个数字,其值必须在可接受的范围内 @Past被注释的元素必须是一个过去的日期 @Future 被注释的元素必须是一个将来的日期 11)全局处理Controller异常: 相关注解: @ControllerAdvice :注解定义全局异常处理类,定义在类上 @ExceptionHandler :注解声明异常处理方法,定义在方法上 12)json数据处理 @JsonIgnoreProperties注解:过滤json数据,作用在类上用于过滤掉特定字段不返回或者不解析。 @JsonIgnore注解:一般用于类的属性上,作用和上面的@JsonIgnoreProperties 一样。 @JsonFormat注解:用于格式化json数据 13)测试相关 @ActiveProfiles注解:作用于测试类上,用于声明生效的Spring配置文件 @Test注解:声明一个方法为测试方法 @Transactional注解:被声明的测试方法的数据会回滚,避免污染测试数据。 @WithMockUser注解: Spring Security 提供的,用来模拟一个真实用户,并且可以赋予权限。
|