Spring中bean的生命周期
如上图我们大致可以将spring生命周期分为12个步骤
- 通过反射实例化对象。
- 设置对象的属性。
- 如果对象实现了BeanNameAware接口,spring将bean的id传递给setBeanName()方法
- 如果对象实现了BeanFactoryAware接口,spring将BeanFactory容器传给setBeanFactory()方法。
- 如果对象实现了ApplicationContextAware接口,spring将bean所在应用上下文传给setApplicationContext()方法。
- 如果对象实现了BeanPostProcessor接口,Spring就将调用他们的。postProcessBeforeInitialization()方法。
- 如果对象实现了InitializingBean接口,spring将调用afterPropertiesSet()方法。
- 如果对象声明了init-method方法,spring将调用该方法。
- 如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的。postProcessAfterInitialization()方法。
- 对象使用中。
- 如果对象实现了DisposableBean()接口,spring将调用destroy()方法。
- 如果对象声明了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 |
|
源码:
1 | // |
将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的几种方式
- 基于XML配置
- 基于注解配置
- 基于Java类的配置
Spring默认是单例还是多例,怎么实现多例
答:默认是单例,如果要实现多例需要在scope属性上设置为“prototype”
1 | XML |
说一下什么是Spring
Spring是一种轻量级开发框架,主旨在于提高开发者的效率和系统的维护性。我们一般说Spring框架指的是Spring Framework使用这些模块可以很方便的协助我们开发。这些模块是:核心容器、数据访问/集成、Web、AOP(面向切面编程)、工具、消息和测试模块。比如:Core Container中的Core组件是Spring所有组件的核心,Beans组件和Context组件是实现IOC和依赖注入的基础,AOP组件用来实现面向切面编程。
Spring模块中的七大模块:
- Spring Core 核心容器提供基本功能。
- Spring Context上下文则是一个配置文件,负责提供上下文信息,进行国际化、电子邮箱、等功能。
- Spring Aop提供面向对象编程。
- Spring ORM 插入了若干个ORM框架,从而提供了ORM对象的关系工具,其中包括了Hibernate、JDO和 IBatis SQL Map等,所有这些都遵从Spring的通用事物和DAO异常层次结构。
- JDBC、DAO的抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理,和不同数据库供应商所抛出的错误信息。异常层次结构简化了错误处理,并且极大的降低了需要编写的代码数量,比如打开和关闭链接。
- Spring Web上下文模块建立在应用程序上下文模块之上,为基于web的应用程序提供了上下文。所以Spring框架支持与Struts集成,web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
- Spring MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的。MVC容纳了大量视图技术,其中包括JSP、POI等,模型来有JavaBean来构成,存放于m当中,而视图是一个街口,负责实现模型,控制器表示逻辑代码,由c的事情。Spring框架的功能可以用在任何J2EE服务器当中,大多数功能也适用于不受管理的环境。Spring的核心要点就是支持不绑定到特定J2EE服务的可重用业务和数据的访问的对象,毫无疑问这样的对象可以在不同的J2EE环境,独立应用程序和测试环境之间重用。
使用Spring的好处
Spring框架能够让我们更高效的编程和易于维护系统
- 轻量:相对于其他框架Spring显得更轻量。
- 控制反转:Spring通过控制反转实现了低耦合,对象给出他们的依赖,而不是创建或者查找对象所需的依赖。
- 面向切面编程:Spring支持面向切面编程,并且把业务逻辑和系统服务分开。
- MVC框架:Spring的WEB框架是个精心设计的框架,是WEB框架的一个很好的替代品。
- 事务管理: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的区别
- 作用对象不同:@Component作用于类,@Bean作用于方法。
- @Component通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中(使用@ComponentScan注解定义要扫描的路径从中找出识别了需要装配的类自动装配到spring的Bean容器中)。@Bean注解通常是在标有该注解的方法中定义产生这个bean,@Bean告诉Spring这是某个类的实例,当我需要用它的时候还给我。
- @Bean注解比@Component注解的自定义性更强,而且很多地方只能通过@Bean注解来注册Bean,比如第三方库中的类。
SpringMVC从接受请求到返回结果的整个流程
- 客户端(浏览器)发送请求,直接请求到DispatcherServlet。
- DispatcherServlet根据请求细节调用HandlerMapping,解析请求对应的Handler。
- 解析到对应的Handler(也就是Controller)后,开始由HandlerAdapter适配器处理。
- HandlerAdapter会根据Handler来调用真正的处理器来处理请求,并处理相应的业务逻辑。
- 处理器处理完业务后,会返回一个ModelAndView对象,Model是返回的数据对象,View是个逻辑上的View。
- ViewResolver会根据View查找实际的View。
- DispatcherServlet把返回的Model传给View(视图渲染)。
- 把View返回给请求者(浏览器)。
说说Spring的事务
Spring中的事务分为两种:声明式事务和编码式事务
- 编程式事务:在代码中硬编码(不推荐)
- 声明式事务:
- 基于XML方式
- 基于注解方式
说说Spring的事务传播行为
- PROPAGATION_REQUIRED:如果当前事务没有事务的话,就创建一个新事务,如果当前存在事务,就加入该事务。(最常用)
- PROPAGATION_SUPPORTS:如果当前事务存在,就加入该事务,否则就以非事务状态运行。(不常用)
- PROPAGATION_MANDATORY:如果当前事务存在,就加入该事务,否则就抛出异常。(不常用)
- PROPAGATION_REQUIRES_NEW:无论当前事务是否存在,都新建一个事务运行。(有用到过)
- PROPAGATION_NO_SUPPORTED:如果当前事务存在,就将他挂起,以非事务状态运行。(不常用)
- PROPAGATION_NEVER:如果当前事务存在,就抛出异常。(不常用)
- PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行(常用)。
说说Spring的事务隔离级别
- ISOLATION_DEFAULT:使用底层数据库的默认级别,数据库设置什么就使用什么级别。
- ISOLATION_READ_UNCOMMITTED:未提交读,最低隔离级别、事务未提交前,就会被其他事务所读取到。会出现幻读、脏读、不可重复读等问题。
- ISOLATION_READ_COMMITED:提交读,一个事务提交后才会被其他事务所读取到,SQL_SERVER的默认级别。会出现幻读、不可重复读等问题。
- ISOLATION_REPEATABLE_READ:可重复读,保证再一个事务中多次读取一个数据时,结果一致。但会出现幻读。
- 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则无需特定的编译器处理。