抱歉,您的瀏覽器無法訪問本站
本頁面需要瀏覽器支持(啟用)JavaScript
了解詳情 >

Spring中bean的生命周期

upload successful

如上图我们大致可以将spring生命周期分为12个步骤

  1. 通过反射实例化对象。
  2. 设置对象的属性。
  3. 如果对象实现了BeanNameAware接口,spring将bean的id传递给setBeanName()方法
  4. 如果对象实现了BeanFactoryAware接口,spring将BeanFactory容器传给setBeanFactory()方法。
  5. 如果对象实现了ApplicationContextAware接口,spring将bean所在应用上下文传给setApplicationContext()方法。
  6. 如果对象实现了BeanPostProcessor接口,Spring就将调用他们的。postProcessBeforeInitialization()方法。
  7. 如果对象实现了InitializingBean接口,spring将调用afterPropertiesSet()方法。
  8. 如果对象声明了init-method方法,spring将调用该方法。
  9. 如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的。postProcessAfterInitialization()方法。
  10. 对象使用中。
  11. 如果对象实现了DisposableBean()接口,spring将调用destroy()方法。
  12. 如果对象声明了destroy-method方法,spring将调用该方法。

Spring是什么?

Spring是一个轻量级的IOC和AOP的框架,是为java应用程序提供基础服务的一套框架。目的是用于简化企业应用程序的开发,使开发者只用关心业务的开发。

主要由以下几个模块组成:

|模块名|介绍|
|Spring Core|核心类库,提供IOC服务|
|Spring Context|提供框架的Bean服务,以及企业级功能|
|Spring Aop|提供Aop服务|
|Spring ORM|提供对ORM框架支持|
|Spring Web|面向Web服务|

Spring你用过哪些注解?

@SpringBootApplication

这个注解是 Spring Boot 项目的基石,创建 SpringBoot 项目之后会默认在主类加上。

1
2
3
4
5
6
7

@SpringBootApplication
public class SpringSecurityJwtGuideApplication {
public static void main(java.lang.String[] args) {
SpringApplication.run(SpringSecurityJwtGuideApplication.class, args);
}
}

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.core.annotation.AliasFor;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
@AliasFor(
annotation = EnableAutoConfiguration.class
)
Class<?>[] exclude() default {};

@AliasFor(
annotation = EnableAutoConfiguration.class
)
String[] excludeName() default {};

@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackages"
)
String[] scanBasePackages() default {};

@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackageClasses"
)
Class<?>[] scanBasePackageClasses() default {};

@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}

将SpringBootApplication可以分为三个注解 @SpringBootConfiguration(跟Configuration一样滴)* @EnableAutoConfiguration *, @ComponentScan的组合。
这三个注解的作用如下:

  • @EnableAutoConfiguration:启用 SpringBoot 的自动配置机制
  • @ComponentScan: 扫描被@Component (@Service,@Controller)注解的 bean,注解默认会扫描该类所在的包下所有的类。
  • @Configuration:允许在 Spring 上下文中注册额外的 bean 或导入其他配置类

@Autowired

将相同类型的对象注入进被@Autowired修饰的对象中

@Component,@Repository,@Service,@Controller,@Configuration

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

@RestController

@RestController注解是@Controller和@ResponseBody的合集,表示这是个控制器 bean,并且是将函数的返回值直 接填入 HTTP 响应体中,是 REST 风格的控制器。

@GetMapping,@PostMapping,@PutMapping,@DeleteMapping

  • @GetMapping: 对应Get请求,请求从服务器获得一个资源
  • @PostMapping: 对应Post请求,在服务器上创建一个新的资源
  • @PutMapping: 对应Put请求,修改服务器一个资源
  • @DeleteMapping: 对应Delete请求,删除服务器一个资源

@PathVariable,@RequestParam,@RequestBody

  • @PathVariable: 获得请求路径上的参数
  • @RequestParam: 获得请求路径后的请求参数
  • @RequestBody: 获得请求体中的JSON数据格式,并映射成所需对象

@Value

读取配置文件的值

Spring声明Bean的几种方式

  1. 基于XML配置
  2. 基于注解配置
  3. 基于Java类的配置

Spring默认是单例还是多例,怎么实现多例

答:默认是单例,如果要实现多例需要在scope属性上设置为“prototype”

1
2
3
4
5
6
7
8
XML

<bean id="自定义id(一般为类名小写)" class="自定义类" init-method="init" scope="prototype">


Java

@Scope("prototype")

说一下什么是Spring

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

Spring模块中的七大模块:

  1. Spring Core 核心容器提供基本功能。
  2. Spring Context上下文则是一个配置文件,负责提供上下文信息,进行国际化、电子邮箱、等功能。
  3. Spring Aop提供面向对象编程。
  4. Spring ORM 插入了若干个ORM框架,从而提供了ORM对象的关系工具,其中包括了Hibernate、JDO和 IBatis SQL Map等,所有这些都遵从Spring的通用事物和DAO异常层次结构。
  5. JDBC、DAO的抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理,和不同数据库供应商所抛出的错误信息。异常层次结构简化了错误处理,并且极大的降低了需要编写的代码数量,比如打开和关闭链接。
  6. Spring Web上下文模块建立在应用程序上下文模块之上,为基于web的应用程序提供了上下文。所以Spring框架支持与Struts集成,web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
  7. Spring MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的。MVC容纳了大量视图技术,其中包括JSP、POI等,模型来有JavaBean来构成,存放于m当中,而视图是一个街口,负责实现模型,控制器表示逻辑代码,由c的事情。Spring框架的功能可以用在任何J2EE服务器当中,大多数功能也适用于不受管理的环境。Spring的核心要点就是支持不绑定到特定J2EE服务的可重用业务和数据的访问的对象,毫无疑问这样的对象可以在不同的J2EE环境,独立应用程序和测试环境之间重用。

使用Spring的好处

Spring框架能够让我们更高效的编程和易于维护系统

  1. 轻量:相对于其他框架Spring显得更轻量。
  2. 控制反转:Spring通过控制反转实现了低耦合,对象给出他们的依赖,而不是创建或者查找对象所需的依赖。
  3. 面向切面编程:Spring支持面向切面编程,并且把业务逻辑和系统服务分开。
  4. MVC框架:Spring的WEB框架是个精心设计的框架,是WEB框架的一个很好的替代品。
  5. 事务管理:Spring提供一个持续的事务管理接口,提供声明式事务和编程式事务。

ps:耦合指的是模块之间的依赖程度

什么是Spring IOC

“spring ioc指的是控制反转,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。交由Spring来管理这些,实现解耦”

说说IOC的优缺点

优点是实现了组件的解耦,提高程序的灵活性和健壮性和可维护性

缺点是IOC容器生成对象是通过反射来实现的,在效率上会有先损耗,但对于IOC容器带来的灵活性和可维护性来说,是微不足道的。

什么是Spring AOP

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

说说Spring bean的作用域

singleton:唯一Bean实例,Spring中的Bean默认都是单例的。

prototype:每次请求都会创建一个新的bean实例。

request:每次HTTP请求都会产生一个新的Bean,该Bean仅在当前HTTP request内有效。

session:每次HTTP请产生一个新的Bean,该Bean仅在当前HTTP session内有效。

说说@Component和@Bean的区别

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

SpringMVC从接受请求到返回结果的整个流程

  1. 客户端(浏览器)发送请求,直接请求到DispatcherServlet。
  2. DispatcherServlet根据请求细节调用HandlerMapping,解析请求对应的Handler。
  3. 解析到对应的Handler(也就是Controller)后,开始由HandlerAdapter适配器处理。
  4. HandlerAdapter会根据Handler来调用真正的处理器来处理请求,并处理相应的业务逻辑。
  5. 处理器处理完业务后,会返回一个ModelAndView对象,Model是返回的数据对象,View是个逻辑上的View。
  6. ViewResolver会根据View查找实际的View。
  7. DispatcherServlet把返回的Model传给View(视图渲染)。
  8. 把View返回给请求者(浏览器)。

说说Spring的事务

Spring中的事务分为两种:声明式事务和编码式事务

  1. 编程式事务:在代码中硬编码(不推荐)
  2. 声明式事务:
    1. 基于XML方式
    2. 基于注解方式

说说Spring的事务传播行为

  1. PROPAGATION_REQUIRED:如果当前事务没有事务的话,就创建一个新事务,如果当前存在事务,就加入该事务。(最常用)
  2. PROPAGATION_SUPPORTS:如果当前事务存在,就加入该事务,否则就以非事务状态运行。(不常用)
  3. PROPAGATION_MANDATORY:如果当前事务存在,就加入该事务,否则就抛出异常。(不常用)
  4. PROPAGATION_REQUIRES_NEW:无论当前事务是否存在,都新建一个事务运行。(有用到过)
  5. PROPAGATION_NO_SUPPORTED:如果当前事务存在,就将他挂起,以非事务状态运行。(不常用)
  6. PROPAGATION_NEVER:如果当前事务存在,就抛出异常。(不常用)
  7. PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行(常用)。

说说Spring的事务隔离级别

  1. ISOLATION_DEFAULT:使用底层数据库的默认级别,数据库设置什么就使用什么级别。
  2. ISOLATION_READ_UNCOMMITTED:未提交读,最低隔离级别、事务未提交前,就会被其他事务所读取到。会出现幻读、脏读、不可重复读等问题。
  3. ISOLATION_READ_COMMITED:提交读,一个事务提交后才会被其他事务所读取到,SQL_SERVER的默认级别。会出现幻读、不可重复读等问题。
  4. ISOLATION_REPEATABLE_READ:可重复读,保证再一个事务中多次读取一个数据时,结果一致。但会出现幻读。
  5. ISOLATON_SERIALIZABLE:序列化,代价最高的隔离级别,该级别能够防止出现脏读、不可重复读、幻读。

脏读:表示一个事务能够读取另一个事务中还未提交的数据。比如,某个事务尝试插入记录 A,此时该事务还未提交,然后另一个事务尝试读取到了记录 A。

不可重复读:表示再一个事务中多次读取一个数据时,结果不一致。

幻读:在一个事务中使用相同的 SQL 两次读取,第二次读取到了其他事务新插入的行。

Spring AOP and AspectJ AOP 有什么区别?

  • AspectJ是静态代理的增强、所谓静态代理,就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强,他会在编译时期将AspectJ织入Java字节码中,这样运行时就是增加后的AOP对象。
  • Spring AOP使用的动态代理分为JDK动态代理、CGLIB代理,所谓的动态代理就是不会取修改字节码,而是在每次运行的时候在内存里生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强的处理。
    • JDK代理只提供接口的代理,不支持类的代理,即需要代理类去实现InvocationHandler接口
    • CGLIB是通过继承的方式来实现动态代理,如果一个类被标记为final,那么它是无法使用CGLIB来做动态代理的

静态代理与动态代理区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式拥有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。