- 1、使用Spring框架的好处是什么?"> 1、使用Spring框架的好处是什么?
- 2、什么是 Spring IOC 容器?
- 3、什么是依赖注入?可以通过多少种方式完成依赖注入?
- 4、BeanFactory 和 ApplicationContext?
- 5、Spring 提供了哪些配置方式?
- 6、Spring 是如何管理 Bean 的?
- 7、Spring 中的 bean 的作用域有哪些? Spring支持集中bean scope?
- 8、说一说 Bean的生命周期?
- 9、Spring是怎么解决循环依赖的?
- 10、什么是 spring 的内部 bean?
- 11、@Autowired 和 @Resource 注解有什么区别?
- 12、@RequestMapping 注解有什么用?
- 13、列举 spring 支持的事务管理类型
- 14、Spring的事务如何配置,常用注解有哪些?
- 15、说一说你对声明式事务的理解
- 16、Spring 中默认提供的单例是线程安全的吗?
- 17、什么是 AOP?
- 18、请你说说AOP的应用场景
- 19、Spring Bean的生命周期?
- 20、Spring Framework 中有多少个模块,它们分别是什么?
- 21、Spring 应用程序有哪些不同组件?
1、使用Spring框架的好处是什么?
- 轻量:Spring 是轻量的,基本的版本大约2MB;
- 控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们;
- 面向切面的编程(AOP):Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开;
- 容器:Spring 包含并管理应用中对象的生命周期和配置;
- MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品;
- 事务管理:Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA);
- 异常处理:Spring 提供方便的API把具体技术相关的异常(比如由JDBC,Hibernate or JDO抛出 的)转化为一致的unchecked 异常。
2、什么是 Spring IOC 容器?
IoC(Inversion of Control)是控制反转的意思,这是一种面向对象编程的设计思想。在不采用这种思想的情况下,我们需要自己维护对象与对象之间的依赖关系,很容易造成对象之间的耦合度过高,在一个大型的项目中这十分的不利于代码的维护。IoC则可以解决这种问题,它可以帮我们维护对象与对象之间的依赖关系,降低对象之间的耦合度。容器创建对象,将它们装配在一起,配置它们并管理它们的完整生命周期。Spring 容器使用依赖注入(DI)来管理组成应用程序的组件。容器通过读取提供的配置元数据来接收对象进行实例化,配置和组装的指令。该元数据可以通过 XML,Java 注解或 Java 代码提供。说到 IoC 就不得不说DI(Dependency Injection),DI是依赖注入的意思,它是IoC实现的实现方式,就是说IoC是通过DI来实现的。由于 IoC 这个词汇比较抽象而 DI 却更直观,所以很多时候我们就用 DI 来代替它,在很多时候我们简单地将 IoC 和 DI 划等号,这是一种习惯。而实现依赖注入的关键是 IoC 容器,它的本质就是一个工厂。
3、什么是依赖注入?可以通过多少种方式完成依赖注入?
在依赖注入中,您不必创建对象,但必须描述如何创建它们。您不是直接在代码中将组件和服务连接在一起,而是描述配置文件中哪些组件需要哪些服务。由 IoC 容器将它们装配在一起。通常,依赖注入可以通过三种方式完成,即:
- 构造函数注入:就是被注入对象可以在它的构造方法中声明依赖对象的参数列表,让外部知道它需要哪些依赖对象。然后,IoC Service Provider 会检查被注入的对象的构造方法,取得它所需要的依赖对象列表,进而为其注入相应的对象。构造方法注入方式比较直观,对象被构造完成后,即进入就绪状态,可以马上使用。
- setter 注入:通过 setter 方法,可以更改相应的对象属性。所以,当前对象只要为其依赖对象所对应的属性添加 setter 方法,就可以通过 setter 方法将相应的依赖对象设置到被注入对象中。setter 方法注入虽不像构造方法注入那样,让对象构造完成后即可使用,但相对来说更宽松一些,可以在对象构造完成后再注入。
- 接口注入:相对于前两种注入方式来说,接口注入没有那么简单明了。被注入对象如果想要 IoC Service Provider 为其注入依赖对象,就必须实现某个接口。这个接口提供一个方法,用来为其注入依赖对象。IoC Service Provider 最终通过这些接口来了解应该为被注入对象注入什么依赖对象。相对于前两种依赖注入方式,接口注入比较死板和烦琐。
4、BeanFactory 和 ApplicationContext?
Spring主要提供了两种类型的容器:BeanFactory 和 ApplicationContext。
BeanFactory 是一个类工厂,与传统类工厂不同的是,BeanFactory 是类的通用工厂,它可以创建并管理各种类的对象。这些可被创建和管理的对象本身没有什么特别之处,仅是一个POJO,Spring称这些被创建和管理的Java对象为Bean。并且,Spring中所说的Bean比JavaBean更为宽泛一些,所有可以被Spring容器实例化并管理的Java类都可以成为Bean。
BeanFactory 是 Spring 容器的顶层接口,Spring 为 BeanFactory 提供了多种实现,最常用的是XmlBeanFactory。但它在 Spring 3.2 中已被废弃,建议使用 XmlBeanDefinitionReader、DefaultListableBeanFactory 替代。BeanFactory最主要的方法就是 getBean(String beanName),该方法从容器中返回特定名称的Bean。
BeanFactory:是基础类型的 IoC 容器,提供完整的 IoC 服务支持。如果没有特殊指定,默认采用延迟初始化策略。只有当客户端对象需要访问容器中的某个受管对象的时候,才对该受管对象进行初始化以及依赖注入操作。所以,相对来说,容器启动初期速度较快,所需要的资源有限。对于资源有限,并且功能要求不是很严格的场景,BeanFactory 是比较合适的IoC容器选择。
ApplicationContext:它是在 BeanFactory 的基础上构建的,是相对比较高级的容器实现,除了拥有BeanFactory 的所有支持,ApplicationContext 还提供了其他高级特性,比如事件发布、国际化信息支持等。ApplicationContext 所管理的对象,在该类型容器启动之后,默认全部初始化并绑定完成。所以,相对于BeanFactory来说,ApplicationContext要求更多的系统资源,同时,因为在启动时就完成所有初始化,容器启动时间较之 BeanFactory 也会长一些。在那些系统资源充足,并且要求更多功能的场景中,ApplicationContext类型的容器是比较合适的选择。
BeanFactory | ApplicationContext |
---|---|
懒加载 | 即时加载 |
使用显式语法提供资源对象 | 自己创建和管理资源对象 |
不支持国际化 | 支持国际化 |
不支持基于依赖的注解 | 支持依赖的注解 |
BeanFactory的优缺点:
- 优点:应用启动的时候占用资源很少,对资源要求较高的应用,比较有优势;
- 缺点:运行速度会相对来说慢一些。而且有可能会出现空指针异常的错误,而且通过 Bean 工厂创建的 Bean生命周期会简单一些。
ApplicationContext的优缺点:
- 优点:所有的 Bean 在启动的时候都进行了加载,系统运行的速度快;在系统启动的时候,可以发现系统中的配置问题。
- 缺点:把费时的操作放到系统启动中完成,所有的对象都可以预加载,缺点就是内存占用较大。
5、Spring 提供了哪些配置方式?
基于 xml 配置: bean 所需的依赖项和服务在 XML 格式的配置文件中指定。这些配置文件通常包含许多 bean 定义和特定于应用程序的配置选项。它们通常以 bean 标签开头。例如:
基于注解配置: 您可以通过在相关的类,方法或字段声明上使用注解,将 bean 配置为组件类本身,而不是使用 XML 来 描述 bean 装配。默认情况下,Spring 容器中未打开注解装配。因此,您需要在使用它之前在 Spring 配 置文件中启用它。例如:<bean id="studentbean" class="org.edureka.firstSpring.StudentBean">
<property name="name" value="Edureka"></property>
</bean>
基于 Java API 配置: Spring 的 Java 配置是通过使用 @Bean 和 @Configuration 来实现。<beans>
<context:annotation-config/>
<!-- bean definitions go here -->
</beans>
- @Bean 注解扮演与元素相同的角色。
- @Configuration 类允许通过简单地调用同一个类中的其他 @Bean 方法来定义 bean 间依赖关系。
例如:
@Configuration
public class StudentConfig {
@Bean
public StudentBean myStudent() {
return new StudentBean();
}
}
6、Spring 是如何管理 Bean 的?
Spring 通过 IoC 容器来管理 Bean,我们可以通过 XML 配置或者注解配置,来指导 IoC 容器对 Bean 的管理。因为注解配置比 XML 配置方便很多,所以现在大多时候会使用注解配置的方式。
以下是管理Bean时常用的一些注解:
- @ComponentScan 用于声明扫描策略,通过它的声明,容器就知道要扫描哪些包下带有声明的类,也可以知道哪些特定的类是被排除在外的。
- @Component、@Repository、@Service、@Controller 用于声明 Bean,它们的作用一样,但是语义不同。@Componen t用于声明通用的 Bean,@Repository 用于声明 DAO 层的 Bean,@Service 用于声明业务层的 Bean,@Controller 用于声明视图层的控制器 Bean,被这些注解声明的类就可以被容器扫描并创建。
- @Autowired、@Qualifier 用于注入 Bean,即告诉容器应该为当前属性注入哪个 Bean。其中,@Autowired 是按照 Bean 的类型进行匹配的,如果这个属性的类型具有多个 Bean,就可以通过@Qualifier 指定 Bean 的名称,以消除歧义。
- @Scope 用于声明 Bean 的作用域,默认情况下 Bean 是单例的,即在整个容器中这个类型只有一个实例。可以通过 @Scope 注解指定 prototype 值将其声明为多例的,也可以将 Bean 声明为 session 级作用域、request 级作用域等等,但最常用的还是默认的单例模式。
- @PostConstruct、@PreDestroy 用于声明 Bean 的生命周期。其中,被 @PostConstruct 修饰的方法将在 Bean 实例化后被调用,@PreDestroy 修饰的方法将在容器销毁前被调用。
7、Spring 中的 bean 的作用域有哪些? Spring支持集中bean scope?
默认情况下,Bean 在 Spring 容器中是单例的,我们可以通过 @Scope 注解修改 Bean 的作用域。该注解有如下5个取值,它们代表了 Bean 的5种不同类型的作用域:
类型 | 说明 |
---|---|
singleton | 在 Spring 容器中仅存在一个实例,即 Bean 以单例的形式存在。 |
prototype | 每次调用 getBean() 时,都会执行 new 操作,返回一个新的实例。 |
request | 每次 HTTP 请求都会创建一个新的 Bean。 |
session | 同一个 HTTP Session 共享一个 Bean,不同的 HTTP Session 使用不同的Bean。 |
globalSession | 同一个全局的 Session 共享一个 Bean,一般用于Portlet环境。 |
8、说一说 Bean的生命周期?
面试题:Spring Bean的生命周期
主要把握创建过程和销毁过程这两个大的方面;
创建过程:
- 首先实例化 Bean,并设置Bean的属性;
- 根据其实现的 Aware 接口(主要是 BeanFactoryAware接口,BeanFactoryAware,ApplicationContextAware)设置依赖信息;
- 接下来调用 BeanPostProcess 的 postProcessBeforeInitialization方法,完成initial前的自定义逻辑;afterPropertiesSet 方法做一些属性被设定后的自定义的事情;
- 调用Bean自身定义的init方法,去做一些初始化相关的工作;然后再调用 postProcessAfterInitialization 去做一些bean初始化之后的自定义工作。
- 此时,Bean 初始化完成,可以使用这个 Bean 了。
销毁过程:如果实现了DisposableBean的destroy方法,则调用它,如果实现了自定义的销毁方法,则调用之。
9、Spring是怎么解决循环依赖的?
10、什么是 spring 的内部 bean?
只有将 bean 用作另一个 bean 的属性时,才能将 bean 声明为内部 bean。为了定义bean,Spring 的基于 XML 的配置元数据在
例如,假设我们有一个 Student 类,其中引用了 Person 类。这里我们将只创建一个 Person 类实例并在 Student 中使用它。
public class Student {
private Person person;
//Setters and Getters
}
public class Person {
private String name;
private String address;
//Setters and Getters
}
<bean id=“StudentBean" class="com.edureka.Student">
<property name="person">
<!--This is inner bean -->
<bean class="com.edureka.Person">
<property name="name" value="Scott"></property>
<property name="address" value="Bangalore"></property>
</bean>
</property>
</bean>
11、@Autowired 和 @Resource 注解有什么区别?
@Autowired | @Resource |
---|---|
Spring提供的注解 | JDK提供的注解 |
只能按类型注入,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它 required 属性为false,如果我们想使用按名称装配,可以结合@Qualifier 注解一起使用。 | 默认按名称注入,也支持按类型注入。 @Resource有两个中重要的属性:name和type。name 属性指定 byName,如果没有指定 name 属性,当注解标注在字段上,即默认取字段的名称作为bean 名称寻找依赖对象,当注解标注在属性的 setter方法上,即默认取属性名作为 bean 名称寻找依赖对象。 需要注意的是,@Resource 如果没有指定 name 属性,并且按照默认的名称仍然找不到依赖对象时, @Resource 注解会回退到按类型装配。但一旦指定了name 属性,就只能按名称装配了。 |
12、@RequestMapping 注解有什么用?
@RequestMapping 注解用于将特定 HTTP 请求方法映射到将处理相应请求的控制器中的特定类/方法。此注释可应用于两个级别:
- 程序化事务管理:在此过程中,在编程的帮助下管理事务。它为您提供极大的灵活性,但维护起来非常困难。
- 声明式事务管理:在此,事务管理与业务代码分离。仅使用注解或基于 XML 的配置来管理事务。
14、Spring的事务如何配置,常用注解有哪些?
事务的打开、回滚和提交是由事务管理器来完成的,我们使用不同的数据库访问框架,就要使用与之对应的事务管理器。在Spring Boot中,当你添加了数据库访问框架的起步依赖时,它就会进行自动配置,即自动实例化正确的事务管理器。
对于声明式事务,是使用 「@Transactional」 进行标注的。这个注解可以标注在类或者方法上。
- 当它标注在类上时,代表这个类所有公共(public)非静态的方法都将启用事务功能。
- 当它标注在方法上时,代表这个方法将启用事务功能。
另外,在@Transactional注解上,我们可以使用 isolation 属性声明事务的隔离级别,使用 propagation 属性声明事务的传播机制。
15、说一说你对声明式事务的理解
Spring事务管理的亮点在于声明式事务管理,它允许我们通过声明的方式,在 IoC 配置中指定事务的边界和事务属性,Spring会自动在指定的事务边界上应用事务属性。相对于编程式事务来说,这种方式十分的方便,只需要在需要做事务管理的方法上,增加 @Transactional 注解,以声明事务特征即可。
16、Spring 中默认提供的单例是线程安全的吗?
不是。当多个用户同时请求一个服务时,容器会给每一个请求分配一个线程,这时多个线程会并发执行该请求对应的业务逻辑(成员方法),此时就要注意了,如果该处理逻辑中有对单例状态的修改(体现为该单例的成员属性),则必须考虑线程同步问题。 线程安全问题都是由全局变量及静态变量引起的。 若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑「线程同步」,否则就可能影响线程安全.。
Spring容器本身并没有提供Bean的线程安全策略。
如果单例的Bean是一个无状态的Bean,即线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例的Bean是线程安全的。比如,Controller、Service、DAO这样的组件,通常都是单例且线程安全的。
如果单例的Bean是一个有状态的Bean,则可以采用「ThreadLocal」对状态数据做线程隔离,来保证线程安全。
17、什么是 AOP?
AOP(Aspect Oriented Programming)是面向切面编程,它是一种编程思想,是面向对象编程(OOP)的一种补充。面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面。如下图,可以很形象地看出,所谓切面,相当于应用对象间的横切点,我们可以将其单独抽象为单独的模块。
AOP可以有多种实现方式,而Spring AOP支持如下两种实现方式。
- JDK动态代理:这是Java提供的动态代理技术,可以在运行时创建接口的代理实例。Spring AOP默认采用这种方式,在接口的代理实例中织入代码。通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口 。JDK 动态代理的核心是 InvocationHandler 接口和 Proxy 类 。
- CGLib动态代理:采用底层的字节码技术,在运行时创建子类代理的实例。当目标对象不存在接口时,Spring AOP 就会采用这种方式,在子类实例中织入代码。CGLIB ( Code Generation Library ),是一个代码生成的类库,可以在运行 时动态的生成某个类的子类,注意, CGLIB 是通过继承的方式做的动态代理,因此如果某个 类被标记为 final ,那么它是无法使用 CGLIB 做动态代理的。
AOP的术语:
- 连接点(join point):对应的是具体被拦截的对象,因为 Spring 只能支持方法,所以被拦截的对象往往就是指特定的方法,AOP 将通过动态代理技术把它织入对应的流程中。
- 切点(point cut):有时候,我们的切面不单单应用于单个方法,也可能是多个类的不同方法,这时,可以通过正则式和指示器的规则去定义,从而适配连接点。切点就是提供这样一个功能的概念。
- 通知(advice):就是按照约定的流程下的方法,分为前置通知、后置通知、环绕通知、事后返回通知和异常通知,它会根据约定织入流程中。
- 目标对象(target):即被代理对象。
- 引入(introduction):是指引入新的类和其方法,增强现有 Bean 的功能。
- 织入(weaving):它是一个通过动态代理技术,为原有服务对象生成代理对象,然后将与切点定义匹配的连接点拦截,并按约定将各类通知织入约定流程的过程。
- 切面(aspect):是一个可以定义切点、各类通知和引入的内容,SpringAOP 将通过它的信息来增强Bean 的功能或者将对应的方法织入流程。
18、请你说说AOP的应用场景
Spring AOP 为 IoC 的使用提供了更多的便利,一方面,应用可以直接使用 AOP 的功能,设计应用的横切关注点,把跨越应用程序多个模块的功能抽象出来,并通过简单的 AOP 的使用,灵活地编制到模块中,比如可以通过AOP 实现应用程序中的日志功能。另一方面,在 Spring 内部,一些支持模块也是通过 Spring AOP 来实现的,比如事务处理。从这两个角度就已经可以看到 Spring AOP 的核心地位了。
19、Spring Bean的生命周期?
20、Spring Framework 中有多少个模块,它们分别是什么?
Spring 核心容器 – 该层基本上是 Spring Framework 的核心。它包含以下模块:
- Spring Core · Spring Bean · SpEL (Spring Expression Language)
- Spring Context
数据访问/集成 – 该层提供与数据库交互的支持。它包含以下模块:
- JDBC (Java DataBase Connectivity)
- ORM (Object Relational Mapping)
- OXM (Object XML Mappers) · JMS (Java Messaging Service)
- Transaction
Web – 该层提供了创建 Web 应用程序的支持。它包含以下模块:
- Web
- Web – Servlet
- Web – Socket
- Web – Portlet
AOP
- 该层支持面向切面编程
Instrumentation
- 该层为类检测和类加载器实现提供支持。
Test - 该层为使用 JUnit 和 TestNG 进行测试提供支持。
21、Spring 应用程序有哪些不同组件?
Spring 应用一般有以下组件:
- 接口 - 定义功能。
- Bean 类 - 它包含属性,setter 和 getter 方法,函数等。
- Spring 面向切面编程(AOP) - 提供面向切面编程的功能。
- Bean 配置文件 - 包含类的信息以及如何配置它们。
- 用户程序 - 它使用接口。