Spring 框架面试题

打印 上一主题 下一主题

主题 697|帖子 697|积分 2091

目录
一、Spring是什么?
二、Spring的AOP明白?
三、Spring的IOC明白?
四、BeanFactory 和 ApplicationContext 有什么区别?
五、请解释Spring Bean 的生命周期?
六、解释 Spring 支持的几种 bean 的作用域。
七、利用注解之前要开启自动扫描功能
八、Spring 框架中都用到了哪些计划模式?
九、Spring事件的实现方式和实现原理


一、Spring是什么?

Spring 是一个轻量级的 IoC 和 AOP 容器框架。是为 Java 应用程序提供底子性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。常见的配置方式有三种:基于 XML 的配置.基于注解的配置.基于 Java 的配置。
主要由以下几个模块组成:
Spring Core :焦点类库,提供 IOC 服务;
Spring Context :提供框架式的 Bean 访问方式以及企业级功能 (JNDI.定时任务等);
Spring AOP · AOP 服务;
Spring DAO :对 JDBC 的抽象,简化了数据访问异常的处理;
Spring ORM :对现有的 ORM 框架的支持;
Spring web 提供了根本的面向 web 的综合特性,比方多方文件上传;
Spring MVC :提供面向 Web 应用的 Model-View-Controller 实现。
二、Spring的AOP明白?

OOP 面向对象,允许开发者定义纵向的关系,但并适用于定义横向的关系,导致了大量代码的重复,而倒霉于各个模块的重用。从而衍生出AOP。
AOP ,一样平常称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共举动和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为"切面'( Aspect ),淘汰体系中的重复代码,低落了模块间的耦合度,同时进步了体系的可维护性。可用于权限认证.日志.事件处理。

AOP 实现的关键在于代理模式, AOP 代理主要分为静态代理和动态代理。静态代理的代表为 AspectJ ;动态代理则以 spring AOP 为代表。
( 1 ) AspectJ 是静态代理的增强,所谓静态代理,就是 AOP 框架会在编译阶段生成 AOP 代理类,因此也称为编译时增强,他会在编译阶段将 AspectJ (切面)织入到Java 字节码中,运行的时间就是增强之后的 AOP 对象。
( 2 ) Spring AOP 利用的动态代理,所谓的动态代理就是说 AOP 框架不会去修改字节码,而是每次运行时在内存中暂时为方法生成一个 AOP 对象,这个AOP 对象包罗了目的对象的全部方法,而且在特定的切点做了增强处理,并回调原对象的方法。

Spring AOP 中的动态代理主要有两种方式 JDK 动态代理和 CGLIB 动态代理:
(1)JDK 动态代理只提供接口的代理,不支持类的代理。焦点InvocationHandler 接口和 Proxy 类, InvocationHandler 通过 invoke() 方法反射来调用目的类中的代码,动态地将横切逻辑和业务编织在一起;接着, Proxy利用 InvocationHandler 动态创建一个符合某一接口的的实例,生成目的类的代理对象。
( 2 )假如代理类没有实现 InvocationHandler 接口,那么 Spring AOP 会选择利用 CGLIB 来动态代理目的类。 CGLIB ( Code Generation Library ),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现 AOP。 CGLIB 是通过继承的方式做的动态代理,因此假如某个类被标记为 final ,那么它是无法利用 CGLIB 做动态代理的。
( 3 )静态代理与动态代理区别在于生成 AOP 代理对象的时机不同,相对来说 AspectJ 的静态代理方式具有更好的性能,但是 AspectJ 需要特定的编译器进行处理而 Spring AOP 则无需特定的编译器处理。InvocationHandIer 的invoke(ObJect proxy,Method method,Object[] a rgs): proxy 是终极生成的代理实例; method 是被代理目的实例的某个详细方法; args 是被代理目的实例某个方法的详细入参,在方法反射调用时利用。

步调 1: 添加依赖
  1. <dependencies>
  2.     <!-- Spring AOP -->
  3.     <dependency>
  4.         <groupId>org.springframework</groupId>
  5.         <artifactId>spring-aop</artifactId>
  6.         <version>5.3.10</version> <!-- Use the appropriate version -->
  7.     </dependency>
  8.     <!-- AspectJ -->
  9.     <dependency>
  10.         <groupId>org.aspectj</groupId>
  11.         <artifactId>aspectjweaver</artifactId>
  12.         <version>1.9.7</version> <!-- Use the appropriate version -->
  13.     </dependency>
  14. </dependencies>
复制代码
步调 2: 定义一个简单的服务
定义一个简单的服务类,我们将在其方法上应用AOP。
  1. public class SimpleService {
  2.     public void performTask() {
  3.         System.out.println("Performing task...");
  4.     }
  5. }
复制代码
步调 3: 定义一个Aspect
创建一个Aspect类,其中包罗通知(Advice)和切点(Pointcut)。
  1. import org.aspectj.lang.annotation.Aspect;
  2. import org.aspectj.lang.annotation.Before;
  3. import org.aspectj.lang.annotation.Pointcut;
  4. @Aspect
  5. public class LoggingAspect {
  6.     // 定义一个切点,匹配SimpleService类的performTask方法
  7.     @Pointcut("execution(* SimpleService.performTask(..))")
  8.     public void logPointcut() {
  9.     }
  10.     // 在匹配的切点上应用前置通知
  11.     @Before("logPointcut()")
  12.     public void logBefore() {
  13.         System.out.println("Method is about to be called...");
  14.     }
  15. }
复制代码
步调 4: 配置Spring以启用AOP
在Spring配置文件中启用AOP并声明Aspect。
  1. import org.springframework.context.annotation.Bean;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.context.annotation.EnableAspectJAutoProxy;
  4. @Configuration
  5. @EnableAspectJAutoProxy // 启用AspectJ自动代理
  6. public class AppConfig {
  7.     @Bean
  8.     public SimpleService simpleService() {
  9.         return new SimpleService();
  10.     }
  11.     @Bean
  12.     public LoggingAspect loggingAspect() {
  13.         return new LoggingAspect();
  14.     }
  15. }
复制代码
步调 5: 运行应用程序
最后,运行你的应用程序并调用SimpleService的performTask方法,你将看到AOP见效,控制台打印了日志信息。
  1. Method is about to be called...
  2. Performing task...
复制代码
三、Spring的IOC明白?

( 1 ) IOC 就是控制反转,是指创建对象的控制权的转移,从前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到 Spring 容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间疏松耦合,也利于功能的复用。 DI 依赖注入,和控制反转是同一个概念的不同角度的描述,即应用程序在运行时依赖 IoC 容器来动态注入对象需要的外部资源。
( 2 )最直观的表达就是 ,IOC 让对象的创建不用去 new 了可以由 spring自动生产,利用 java 的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法。
( 3 ) Spring 的 IOC 有三种注入方式:构造器注入 .setter 方法注入.根据注解注入。IOC 让相互协作的组件保持疏松的耦合,而 AOP 编程允许你把遍布于应用各层的功能分离出来形成可重用的功能组件。
四、BeanFactory 和 ApplicationContext 有什么区别?

BeanFactory 和 ApplicationContext 是 Spring 的两大焦点接口,都可以当做 Spring 的容器。其中 ApplicationContext 是 BeanFactory 的子接口。
( 1 ) BeanFactory :是 Spring 里面最底层的接口包罗了各种 Bean 的定义,读取 bean 配置文档,管理 bean 的加载·实例化,控制 bean 的生命周期,维护 bean 之间的依赖关系。 ApplicationContext 接口作为 BeanFactory 的派生,除了提供 BeanFactory 所具有的功能外,还提供了更完整的框架功能:

  • 继承 MessageSource ,因此支持国际化。
  • 同一的资源文件访问方式。
  • 提供在监听器中注册 bean 的事件。
  • 同时加载多个配置文件。
  • 载入多个(有继承关系)上下文,使得每一个上下文都专注于一个特定的层次,比如应用的 web 层。
( 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 则是自动注册。
五、请解释Spring Bean 的生命周期?

首先说一下 servlet 的生命周期:实例化,初始 init ,吸收请求 service ,烧毁 destroy ;
Spring 上下文中的 Bean 生命周期也类似,如下:
( 1 )实例化 Bean:对于 BeanFactory 容器,当客户向容器请求一个尚未初始化的 bean 时,或初始化 bean 的时间需要注入另一个尚未初始化的依赖时,容器就会调用createBean 进行实例化。对于 ApplicationContext 容器,当容器启动结束后和通过获取 BeanDefinition 对象中的信息,实例化所有的 bean。
( 2 )设置对象属性(依赖注入):实例化后的对象被封装在 BeanWrapper 对象中,紧接着, Spring 根据BeanDefinition 中的信息以及通过 BeanWrapper 提供的设置属性的接口完成依赖注入。
( 3 )实现 Aware 接口:
接着, Spring 会检测该对象是否实现了 xxxAware 接口,并将相关的xxxAware 实例注入给 Bean:假如这个 Bean 已经实现了 BeanNameAware 接口,则会调用它实现的setBeanName(String beanld) 方法,此处传递的就是 Spring 配置文件中 Bean的 id 值,假如这个 Bean 已经实现了 BeanFactoryAware 接口,则会调用它实现的setBeanFactory() 方法,传递的是 Spring 工厂自身。假如这个 Bean 已经实现了 ApplicationContextAware 接口,会调用setApplicationContext(ApplicationContext) 方法,传入 Spring 上下文;
( 4 ) BeanPostProcessor :假如想对 Bean 进行一些自定义的处理,那么可以让 Bean 实现了BeanPostProcessor 接口,那将会调用postProcessBeforeInitialization(Object obj, String s) 方法。由于这个方法是在 Bean 初始化结束时调用的,所以可以被应用于内存或缓存技术;
( 5 ) InitializingBean 与 init-method:假如 Bean 在 Spring 配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。
( 6 )假如这个 Bean 实现了 BeanPostProcessor 接口,将会调用postProcessAfterInitialization(ObJect ObJ, String s )方法;以上几个步调完成后, Bean 就已经被正确创建了,之后就可以利用这个Bean 了。
( 7 ) DisposableBean:当 Bean 不再需要时,会经过清理阶段,假如 Bean 实现了 DisposableBean这个接口,会调用实在现的 destroy() 方法;
( 8 ) destroy-method:最后,假如这个 Bean 的 Spring 配置中配置了 destroy-method 属性,会自动调用其配置的烧毁方法。
六、解释 Spring 支持的几种 bean 的作用域。

Spring 容器中的 bean 可以分为 5 个范围
( 1 ) singleton :默认,每个容器中只有一个 bean 的实例,单例的模式由BeanFactory 自身来维护。
( 2 ) prototype :为每一个 bean 请求提供一个实例。
( 3 ) request :为每一个网络请求创建一个实例,在请求完成以后, bean会失效并被垃圾接纳器接纳。
( 4 ) session :与 request 范围类似,确保每个 session 中有一个 bean 的实例,在 session 过期后, bean 会随之失效。
( 5 ) global-session :全局作用域, global-session 和 Portlet 应用相关。当你的应用部署在 Portlet 容器中工作时,它包罗很多 portlet。 假如你想要声明让所有的 portlet 共用全局的存储变量的话,那么这全局变量需要存储在global-session 中。全局作用域与 Servlet 中的 session 作用域效果雷同。
七、利用注解之前要开启自动扫描功能

步调一:创建配置类并开启组件扫描
创建一个 Java 配置类并利用 @Configuration 注解标记它,表示这是一个Spring 配置类;在配置类中利用@ComponentScan注解来指定Spring应该扫描的包路径。
  1. import org.springframework.context.annotation.Configuration;
  2. import org.springframework.context.annotation.ComponentScan;
  3. @Configuration
  4. @ComponentScan(basePackages = "com.example") // 指定要扫描的包路径
  5. public class AppConfig {
  6.     // 配置其他bean
  7. }
复制代码
步调二:利用注解定义组件
在指定的包路径下创建组件类,并利用相应的注解标记它们:
  1. import org.springframework.stereotype.Component;
  2. @Component // 表示这是一个Spring组件
  3. public class MyComponent {
  4.     // 组件实现
  5. }
复制代码

@Configuration 把一个类作为一个 IoC 容器,它的某个方法头上假如注册 了@Bean ,就会作为这个 Spring 容器中的 Beano
@Scope 注解作用域
@Service 用于标注业务层组件
@Controller 用于标注控制层组件(如 struts 中的 action )
@Repository 用于标注数据访问组件,即 DA0 组件。
@Component 泛指组件,当组件欠好归类的时间,我们可以利用这个注解进行标注。@Scope 用于指定 scope 作用域的(用在类上)
@Autowired 默认按类型装配
八、Spring 框架中都用到了哪些计划模式?

( 1 )工厂模式: BeanFactory 就是简单工厂模式的体现,用来创建对象的实例;
( 2 )单例模式: Bean 默以为单例模式。
( 3 )代理模式: Spring 的 AOP 功能用到了 JDK 的动态代理和 CGLIB 字节码生成。( 4 )模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
( 5 )观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如 Spring 中 listener 的实现--ApplicationListener。
九、Spring事件的实现方式和实现原理

Spring 事件的本质实在就是数据库对事件的支持,没有数据库的事件支持,spring 是无法提供事件功能的。真正的数据库层的事件提交和回滚是通过binlog 大概 redo log 实现的。
( 1 ) Spring 事件的种类:spring 支持编程式事件管理和声明式事件管理两种方式:A.编程式事件管理利用 TransactionTemplate。
B.声明式事件管理建立在 AOP 之上的。其本质是通过 AOP 功能,对方法前后进行拦截,将事件处理的功能编织到拦截的方法中,也就是在目的方法开始前加入一个事件,在实行完目的方法之后根据实行情况提交大概回滚事件。
声明式事件最大的优点就是不需要在业务逻辑代码中掺杂事件管理的代码,只需在配置文件中做相关的事件规则声明 或通过@Transactional 注解的方式,便可以将事件规规则应用到业务逻辑中。声明式事件管理要优于编程式事件管理,这正是 spring 提倡的非侵入式的发方式,使业务代码不受污染,只要加上注解就可以获得完全的事件支持。唯不一足地方是,最细粒度只能作用到方法级别,无法却故到像编程式事件那样可以作用到代码块级别。
( 2 ) spring 的事件传播举动:Spring 事件的传播举动说的是,当多个事件同时存在的时间, Spring 如那边理这些事件的举动。

  • PROPAGATION-REQUIRED :假如当前没有事件,就创建一个新事件,假如当前存在事件,就加入该事件,该设置是最常用的设置。
  • PROPAGATION-SUPPORTS :支持当前事件,假如当前存在事件,就加入该事件,假如当前不存在事件,就以非事件实行。
  • PROPAGATION_MANDATORY :支持当前事件,假如当前存在事件,就加入该事件,假如当前不存在事件,就抛出异常。
  • PROPAGATION_REQUIRES_NEW :创建新事件,无论当前存不存在事件,都创建新事件。
  • PROPAGATION-NOT-SUPPORTED :以非事件方式实行操纵,假如当前存在事件,就把当前事件挂起。
  • PROPAGATION-NEVER :以非事件方式实行,假如当前存在事件,则抛出异常。
  • PROPAGATION-NESTED :假如当前存在事件,则在嵌套事件内实行。假如当前没有事件,则按 REQUIRED 属性实行。
( 3 ) Spring 中的隔离级别:

  • ISOLATION_DEFAULT :这是个 PlatfromTransactionManager 默认的隔离级别,利用数据库默认的事件隔离级别。
  • ISOLATION-READ-UNCOMMITTED :读未提交,允许另外一个事件可以看到这个事件未提交的数据。
  • ISOLATION_READ_COMMITTED :读已提交,保证一个事件修改的数据提交后才能被另一事件读取,而且能看到该事件对已有记录的更新。
  • ISOLATION_REPEATABLE_READ :可重复读,保证一个事件修改的数据提交后才能被另一事件读取,但是不能看到该事件对已有记录的更新。
  • ISOLATION_SERIALIZABLE :一个事件在实行的过程中完全看不到其他事件对数据库所做的更新。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

道家人

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表