1.Spring是什么?作用是什么?
Spring是一个轻量级的JavaEE框架,它主要解决企业应用中的复杂性问题。Spring框架有三个核心部分:IoC容器、AOP和数据访问/集成层。Spring中的IoC容器提供了一种对象创建和对象之间关系管理的机制,以实现松散耦合和可扩展性。AOP提供了一种很好的方式来实现横向关注点的处理,如事务管理,安全检查,缓存等。数据访问/集成层则提供了许多针对不同数据持久化技术的实现,比如JDBC,ORM和NoSQL。
2.你对IoC(控制反转 Inversion of Control)是怎么理解的?
IoC是一种设计思想,通过将对象之间的依赖关系交给容器来管理,从而实现松散耦合。在Spring中,IoC容器扮演了一个中心角色,负责创建对象,装配对象之间的依赖关系,并管理它们的整个生命周期。IoC还提供了一些高级功能,如AOP和事件驱动等,可以进一步增强应用程序的可维护性和可扩展性。
3.什么是AOP(面向切面编程 Aspect Oriented Programming)?
AOP是一种编程范式,它能够在程序运行期间动态地将代码切入到原有代码的流程中,从而实现横向关注点的处理,如日志记录、事务管理和安全检查等。在Spring中,AOP是通过代理模式来实现的,在创建Bean时为Bean生成一个代理对象,代理对象能够拦截指定方法的调用,并在执行前或执行后执行特定操作。
4.Spring中Bean之间的依赖关系是怎样的?
在Spring中,Bean之间的依赖关系主要通过构造函数注入、Setter方法注入和自动注入来实现。构造函数注入是通过Bean的构造方法注入其他Bean作为参数来实现;Setter方法注入是通过Bean的Setter方法来注入其他Bean;自动注入则是通过IoC容器在Bean创建时自动发现并注入其他Bean,可以通过设置@Autowired或@Resource注解来完成。
5.Spring框架中的单例模式是怎样实现的?
在Spring中,默认情况下,所有的Bean都是单例的。当IoC容器创建一个Bean时,它会缓存该Bean的实例,并在后续请求中返回相同的实例。这种机制可以提高应用程序的性能并减少内存消耗,但也需要注意线程安全和状态管理等问题。
6.Spring中的事务管理是如何实现的?
Spring通过AOP在运行时动态地将事务相关的逻辑切入到指定的方法中,从而实现事务管理。通常情况下,Spring使用声明式事务管理来管理事务。开发者可以通过@Transactional注解或XML配置文件来定义事务范围、传播属性以及回滚规则等。
7.Spring的优势是什么?
序号 | 好处 | 说明 |
---|---|---|
1 | 轻量 | Spring 是轻量的,基本的版本大约2MB。 |
2 | 控制反转 | Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,<br>而不是创建或查找依赖的对象们。 |
3 | 面向切面编程(AOP) | Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。 |
4 | 容器 | Spring 包含并管理应用中对象的生命周期和配置。 |
5 | MVC框架 | Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。 |
6 | 事务管理 | Spring 提供一个持续的事务管理接口,<br>可以扩展到上至本地事务下至全局事务(JTA)。 |
7 | 异常处理 | Spring 提供方便的API把具体技术相关的异常 <br>(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked 异常。 |
8.解释一下Spring中的BeanFactory和ApplicationContext有什么区别。
BeanFactory是Spring IoC容器的最基本形式,提供了基本的IoC功能。它是延迟初始化的,即当一个Bean被实际使用时才被创建。ApplicationContext是BeanFactory的子接口,提供了更多的企业级功能,如AOP,事件驱动,国际化等。ApplicationContext也是预初始化的,即在容器启动时就已经创建了所有的Bean。
9.Spring中的注解有哪些?
Spring中的常用注解有:
1)@Component、@Service、@Repository、@Controller:用于标识Bean的角色。
2)@Autowired、@Resource:用于自动装配Bean。
3)@PostConstruct、@PreDestroy:用于指定初始化和销毁方法。
4)@Transactional:用于声明式事务管理。
5)@Scope:用于指定Bean作用域。
10.Spring MVC框架的流程是怎样的?
Spring MVC的处理流程如下:
1)客户端向服务器发起请求。
2)DispatcherServlet接收到请求并将请求发送给处理器映射器进行处理器的映射查找。
3)处理器映射器将请求的URL映射到相应的控制器(Controller)上,并返回处理器及其拦截器(如果有)。
4)DispatcherServlet调用处理器适配器(Adapter)执行映射的处理器(Controller)。
5)处理器(Controller)执行后返回ModelAndView对象。
6)DispatcherServlet将ModelAndView对象交给视图解析器(ViewResolver)进行解析。
7)视图解析器(ViewResolver)解析出对应的视图(View)。
8)DispatcherServlet将Model数据和View视图进行渲染后返回给客户端。
11.Spring Boot是什么?与传统的Spring框架有什么区别?
Spring Boot是一种基于Spring的快速应用开发框架,它能够让开发者更加快速地搭建基于Spring的应用程序,并提供了自动化配置、快速启动等便利功能。相比传统的Spring框架,Spring Boot具有更简洁的配置方式和更快的启动速度,同时还提供了更多的功能和特性支持。
12.解释一下Spring的生命周期。
在Spring中,Bean的生命周期包括以下几个阶段:
1)实例化:当IoC容器读取到Bean的定义后,创建一个新的Bean实例。
2)属性注入:IoC容器将Bean中声明的依赖关系和配置信息注入到Bean中。
3)BeanPostProcessor前置处理:如果Bean中定义了BeanPostProcessor接口的实现类,它们将在Bean初始化之前被调用。
4)初始化:如果Bean实现了InitializingBean接口,则在所有属性都被设置完毕后调用afterPropertiesSet()方法。同时,也可以通过@Bean(initMethod = "init")来指定Bean的初始化方法。
5)BeanPostProcessor后置处理:如果Bean中定义了BeanPostProcessor接口的实现类,它们将在Bean初始化之后被调用。
6)销毁:如果Bean实现了DisposableBean接口,则在容器关闭或者该Bean被从容器中移除时调用destroy()方法。同时,也可以通过@Bean(destroyMethod = "destroy")来指定Bean的销毁方法。
13.Spring中的IOC如何管理对象?
在Spring中,IOC通过Bean工厂来管理对象,Bean工厂是提供了一种对象创建和对象之间关系管理的机制。它在读取配置文件时会自动创建和装配对象,并缓存这些对象以便后续使用。开发者可以通过构造器注入、Setter方法注入和自动注入等方式来管理对象之间的依赖关系。
14.Spring中的AOP的具体实现方式有哪些?
Spring中实现AOP的主要方式有两种:JDK动态代理和CGLIB代理。JDK动态代理又叫接口代理,它是基于Java反射机制实现的,要求目标对象必须实现至少一个接口;CGLIB代理则是基于字节码操作实现的,当目标对象没有实现接口时,它就会使用CGLIB代理。通常情况下,Spring默认使用JDK动态代理来实现AOP,但如果目标对象没有实现任何接口,则会自动切换到使用CGLIB代理。
15.Spring中的JdbcTemplate是什么?使用JdbcTemplate需要做哪些配置?
JdbcTemplate是Spring提供的一个对JDBC访问的封装,它简化了JDBC操作的繁琐和冗长,能够提高开发效率。使用JdbcTemplate需要在Spring的配置文件中配置基本数据源信息、配置JdbcTemplate Bean以及为JdbcTemplate Bean配置数据源。
16.解释一下Spring中的循环依赖问题。
循环依赖指两个或多个Bean之间相互引用,形成了一个无限循环调用的情况。在Spring容器中,如果存在循环依赖,但是都是单例模式的Bean,则可以通过Spring容器提前暴露正在创建的Bean,从而避免循环依赖问题。如果存在循环依赖且其中一方是原型模式的Bean,则Spring无法处理这种情况。
17.Spring中的事件驱动机制是怎样的?有哪些默认事件?
Spring中的事件驱动机制基于观察者模式实现。当一个Bean发生事件时,它会创建一个事件对象并将其发布到Spring容器上。容器中所有对该事件对象感兴趣的Bean都会收到事件通知并进行相应的处理。Spring中默认的事件有:ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent和ContextClosedEvent。
18.Spring的MVC框架中,HandlerAdapter的作用是什么?
HandlerAdapter是Spring MVC框架中的一个重要组件,它的作用是将请求交给相应的处理器(Controller)进行处理,并负责调用处理器的方法来生成ModelAndView对象。
19.@Autowired和@Resource注解用来干嘛的?
@Autowired和@Resource注解是用于自动装配Bean的。@Autowired是Spring提供的注解,可以在Setter方法上、构造函数上、类属性上进行标注,用于自动注入匹配类型的Bean。@Resource是JavaEE提供的注解,可以在Setter方法上或类属性上进行标注,用于自动注入指定名称和类型匹配的Bean。
20.Spring中的事务传播属性有哪些?
事务传播行为类型 | 说明 |
---|---|
REQUIRED | 如果当前事务管理器中没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择,是默认的传播行为。 |
SUPPORTS | 支持当前事务,如果当前事务管理器中没有事务,就以非事务方式执行。 |
MANDATORY | 使用当前的事务,如果当前事务管理器中没有事务,就抛出异常。 |
REQUIRES_NEW | 新建事务,如果当前事务管理器中存在事务,把当前事务挂起,然后会新建一个事务。 |
NOT_SUPPORTED | 以非事务方式执行操作,如果当前事务管理器中存在事务,就把当前事务挂起。 |
NEVER | 以非事务方式执行,如果当前事务管理器中存在事务,则抛出异常。 |
NESTED | 如果当前事务管理器中存在事务,则在嵌套事务内执行;如果当前事务管理器中没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |
注意:这7种传播行为有个前提,他们的事务管理器是同一个的时候,才会有上面描述中的表现行为。
21.什么是依赖注入?
在Spring创建对象的过程中,把对象依赖的属性注入到对象中。依赖注入主要有两种方式:构造器注入和属性注入。
22.BeanFactory和ApplicationContext有什么区别?
BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。
两者区别如下:
1、功能上的区别。BeanFactory是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。
ApplicationContext接口作为BeanFactory的派生,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能,如继承MessageSource、支持国际化、统一的资源文件访问方式、同时加载多个配置文件等功能。
2、加载方式的区别。BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。
而ApplicationContext是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。 ApplicationContext启动后预载入所有的单例Bean,那么在需要的时候,不需要等待创建bean,因为它们已经创建好了。
相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。
3、创建方式的区别。BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。
4、注册方式的区别。BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。
23.Bean的作用域
1、singleton:单例,Spring中的bean默认都是单例的。
2、prototype:每次请求都会创建一个新的bean实例。
3、request:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
4、session:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP session内有效。
5、global-session:全局session作用域。
24.@Autowired和@Resource的区别?
Autowire是spring的注解。默认情况下@Autowired是按类型匹配的(byType)。如果需要按名称(byName)匹配的话,可以使用@Qualifier注解与@Autowired结合。@Autowired 可以传递一个required=false
的属性,false指明当userDao实例存在就注入不存就忽略,如果为true,就必须注入,若userDao实例不存在,就抛出异常。
public class UserServiceImpl implements UserService {//标注成员变量@Autowired@Qualifier("userDao1")private UserDao userDao; }
Resource是j2ee的注解,默认按 byName模式自动注入。@Resource有两个中重要的属性:name和type。name属性指定bean的名字,type属性则指定bean的类型。因此使用name属性,则按byName模式的自动注入策略,如果使用type属性,则按 byType模式自动注入策略。倘若既不指定name也不指定type属性,Spring容器将通过反射技术默认按byName模式注入。
@Resource(name="userDao")
private UserDao userDao;//用于成员变量//也可以用于set方法标注
@Resource(name="userDao")
public void setUserDao(UserDao userDao) {this.userDao= userDao;
}
上述两种自动装配的依赖注入并不适合简单值类型,如int、boolean、long、String以及Enum等,对于这些类型,Spring容器也提供了@Value注入的方式。
@Value和@Autowired、@Resource类似,也是用来对属性进行注入的,只不过@Value是用来从Properties文件中来获取值的,并且@Value可以解析SpEL(Spring表达式)。
比如,jdbc.properties文件如下:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8&allowMultiQueries=true
jdbc.username=root
jdbc.password=root
利用注解@Value获取jdbc.url和jdbc.username的值,实现如下:
public class UserServiceImpl implements UserService {//占位符方式@Value("${jdbc.url}")private String url;//SpEL表达方式,其中代表xml配置文件中的id值configProperties@Value("#{configProperties['jdbc.username']}")private String userName;
}
25.Spring 事务实现方式有哪些?
事务就是一系列的操作原子执行。Spring事务机制主要包括声明式事务和编程式事务。
- 编程式事务:通过编程的方式管理事务,这种方式带来了很大的灵活性,但很难维护。
- 声明式事务:将事务管理代码从业务方法中分离出来,通过aop进行封装。Spring声明式事务使得我们无需要去处理获得连接、关闭连接、事务提交和回滚等这些操作。使用
@Transactional
注解开启声明式事务。
@Transactional
相关属性如下:
属性 | 类型 | 描述 |
---|---|---|
value | String | 可选的限定描述符,指定使用的事务管理器 |
propagation | enum: Propagation | 可选的事务传播行为设置 |
isolation | enum: Isolation | 可选的事务隔离级别设置 |
readOnly | boolean | 读写或只读事务,默认读写 |
timeout | int (in seconds granularity) | 事务超时时间设置 |
rollbackFor | Class对象数组,必须继承自Throwable | 导致事务回滚的异常类数组 |
rollbackForClassName | 类名数组,必须继承自Throwable | 导致事务回滚的异常类名字数组 |
noRollbackFor | Class对象数组,必须继承自Throwable | 不会导致事务回滚的异常类数组 |
noRollbackForClassName | 类名数组,必须继承自Throwable | 不会导致事务回滚的异常类名字数组 |