Spring面试题——第一篇

1. BeanFactory和ApplicationContext有什么区别

- BeanFactory是各种bean集合的工厂类,BeanFactory包含了各种bean的定义,以便在接收到客户端请求时将对应的bean实例化。
BeanFactory还包含了bean生命周期的控制。
- ApplicationContext和Bean factory一样具有bean定义、关联根据请求分发bean的功能,但是ApplicationContext在此基础上
- 还提供了其他功能,如支持国际化文本消息、统一资源文件读取方式等。

2. Spring Bean的生命周期

Spring框架的核心特征之一是IOC容器,他管理着应用程序中对象的创建、配置和管理。Spring Bean是被Spring IOC容器管理的对象。
Bean的生命周期是指从Bean的创建到销毁的整个过程。

1. 创建Bean实例

2. 设置Bean属性
	- Spring会通过反射设置Bean的属性值,这些属性可以是从其他Bean注入的,或者是在配置文件中指定的值。
	- Spring使用@Autowired,@Inject,@Value等注解来自动装配Bean属性。

3. 依赖注入后的处理
	-	Spring会调用Bean的postProcessBeforeInitialization方法来进一步处理Bean。
	-	如果Bean实现了InitializingBean接口,Spring会调用afterPropertiesSet()方法。
	-	如果Bean类中带有@PostConstruct注解的方法,Spring也会调用该方法。
	-	这些步骤用于执行任何必要的初始化操作。

4. 初始化
	- 如果Bean定义中包含了初始化方法(例如init-method属性),Spring也会调用该方法。

5.  Bean处于活动状态

6. 销毁Bean
	- 当Spring容器关闭时,如果Bean实现了DisposableBean接口,Spring会调用destory方法。
	- 如果Bean定义中包含了销毁方法,Spring会调用该方法。
	- 如果Bean类中定义了带有@PreDestroy注解的方法,Spring也会调用该方法

3. Spring IOC如何实现

1.  配置元数据:首先需要定义一个配置元数据,这是Spring IOC容器用来创建和配置Bean的基础。

2.  创建容器:Spring提供了两个主要的容器实现。
	- BeanFactory:这是一个底层的接口,提供了Bean工厂的基本功能
	- ApplicationContext:这是一个更高级的接口

3. 解析配置:当容器启动时,他会解析配置元数据并创建一个内部的数据结构来存储这些信息。

4. Bean实例化:Bean的实例化过程如下
	- 根据Bean定义中指定的构造器创建Bean实例。
	- 如果Bean定义中指定了依赖,Spring会通过构造器注入、setter注入或者其他注入方式来注入依赖。
	- Spring使用BeanPostProcessor接口来允许开发者在Bean实例化前后进行额外的处理。

5. 初始化:Bean实例化后,Spring调用Bean的初始化方法,通常发生在实现了InitializingBean接口的afterPropertiesSet方法
	或通过@PostConstruct注解的方法。

6. Bean的使用

7. 销毁

4. Spring AOP实现原理

Spring AOP是一种编程范式,他允许将横切关注点从业务逻辑中分离出来。在Spring框架中,AOP主要通过代理模式来实现。

Spring AOP实现原理如下:

1. 配置切点:定义哪些连结点应该被通知,通常使用切点表达式来指定方法签名。

2. 创建代理:根据目标对象的类型选择适当的代理对象。
	JDK动态代理:如果目标对象至少实现了一个接口,则Spring AOP会使用JDK动态代理。
	CGLIB动态代理:如果目标对象没有实现接口,Spring AOP会使用CGLIB创建一个子类来代理。

3. 处理方法调用:当客户端代码调用目标对象的方法时,实际上是调用了代理对象。

4. 拦截方法调用:代理对象拦截方法调用,并决定是否需要调用通知。

5. 调用通知:根据配置调用相应的通知。

6. 继续执行:通知完成后,代理对象将调用目标对象的方法。

7. 返回结果:目标方法执行完毕后,代理对象返回结果给客户端代码。

示例:
创建简单的服务类

public class SimpleService {
    public void doSomething() {
        System.out.println("Doing something...");
    }
}

创建切面类

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
	// 第一步:配置切点
    @Before("execution(* com.example.SimpleService.doSomething(..))")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Executing: " + joinPoint.getSignature().getName());
    }
}

注册Bean和切面

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;

@Configuration
public class AppConfig {
    @Bean
    public SimpleService simpleService() {
        return new SimpleService();
    }
	//第五步:拦截调用通知
    @Bean
    public LoggingAspect loggingAspect() {
        return new LoggingAspect();
    }
	// 第二步:创建代理
    @Bean
    public AnnotationAwareAspectJAutoProxyCreator aspectJAutoProxyCreator() {
        return new AnnotationAwareAspectJAutoProxyCreator();
    }
}

使用服务

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        SimpleService simpleService = context.getBean(SimpleService.class);
        //第三步:服务调用
        simpleService.doSomething();
    }
}

5. Spring事务实现方式

Spring框架提供了对事务管理的支持,使得开发者可以容易的控制事务的开始、提交和回滚。
Spring事务管理有两种主要实现方式:编程式事务管理、声明式事务管理。

1. 编程式事务管理:开发者显示的控制事务的开始、提交和回滚。这种方式适用于那些需要对事务有更细粒度控制的场景。

示例:

import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

public class UserService {

    private PlatformTransactionManager transactionManager;

    public UserService(DataSourceTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    public void createUser(User user) {
        TransactionDefinition def = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(def);

        try {
            // 执行数据库操作
            saveUser(user);
            saveUserLog(user); // 假设这是一个记录用户操作日志的方法

            transactionManager.commit(status);
        } catch (Exception e) {
            transactionManager.rollback(status);
            throw e;
        }
    }

    private void saveUser(User user) {
        // 执行保存用户的数据库操作
    }

    private void saveUserLog(User user) {
        // 执行保存用户操作日志的数据库操作
    }
}
2. 注解声明式事务管理
	在Spring中,声明式事务管理通常通过@Transactional注解来实现。

6. Spring事务底层原理

Spring事务主要基于数据库事务和AOP机制来实现的。核心步骤如下

1. 创建代理对象
	当Spring容器检测到某个Bean的方法使用了@Transactional注解,Spring会为这个Bean创建一个代理对象,
这个代理对象会拦截所有对原始Bean方法的调用,并在调用前后执行事务相关的逻辑。

2. 事务的开启和连接处理
 	- 开启事务:当代理对象拦截到一个被@Transactional注解的方法时,Spring首先判断当前是否已经存在一
 个事务,如果不存在,会根据配置的事务管理器(DataSourceTransactionalManager)来开启一个新的事务。
 	- 连接处理:事务管理器会创建一个数据库连接,并将这个连接的autocommit属性设置为false,
 以禁用自动提交。

3. 业务逻辑执行
	在事务上下文中,代理对象会调用原始Bean的方法执行实际的业务逻辑。这些业务逻辑可能包括多个数据库操作。

4. 提交或者回滚事务
	- 提交事务:如果业务逻辑执行成功且没有抛出异常,那么代理对象会在方法返回前调用事务管理器的commit
方法,提交事务并释放数据库连接。
	- 回滚事务:如果业务逻辑执行过程中抛出了异常,那么 *代理对象会捕获这个异常,并调用事务管理器的
rollback方法。

5. 事务传播行为
	Spring还提供了事务的传播行为,允许开发者控制事务的边界和行为。例如,PROPAGATION_REQUIRED表示
当前方法必须运行在事务中,如果当前存在事务,就加入该事务,否则创建一个新的事务。

6. 隔离级别
	事务的隔离级别也是Spring事务管理的一个方面。他定义了事务间的可见性和干扰程度。Spring支持数据
	库的四种标准隔离级别(读未提交、读已提交、可重复读、串行化)。并允许开发者在@Transactional注解
	中指定所需的隔离级别。

7. 底层实现
	Spring事务的实现依赖于数据库的事务机制,真正的数据库层的事务提交和回滚是通过数据库
的日志来实现的。Spring事务管理器只是作为一个中间层,负责协调和管理这些事务。

总结:Spring事务底层原理是一个基于AOP和数据库事务机制的高效过程,他通过代理对象拦截方法调用,在事务上下文中执行业务逻辑,并在适当的时候提交或者回滚事务。同时,Spring还提供了丰富的事务传播行为和隔离级别选项,以满足不同场景下的需求

7. Spring事务的传播行为

Spring事务的传播行为在Spring框架中是一个重要的概念,他定义了当一个事务方法被另一个事务方法调用时,事务应该如何进行。Spring提供了七种事务传播行为。

(1).PROPAGATION_REQUIRED(默认行为)
	a. 如果当前存在事务,则加入该事务;否则,创建  一个新的事务。
	b. 方法A调用方法B,如果A在事务中,B也将在A的事务中运行;如果A不在事务中,则B开启一个新的事务。

(2).PROPAGATION_REQUIRES_NEW
    a.  总是开启一个新的事务
    b.  方法A调用方法B,无论A是否在事务中,B都将开启一个新的、与A无关的事务。
 
(3).PROPAGATION_SUPPORTS
    a.  如果当前存在事务,则加入该事务;否则,以非事务的方式继续运行。

(4).PROPAGATION_MANDATORY
	a. 如果当前存在事务,则加入该事务;否则,抛出异常。

(5).PROPAGATION_NOT_SUPPORTED
	a. 以非事务的方式运行,如果当前存在事务,则把事务挂起。

(6).PROPAGATION_NEVER
	a. 以非事务的方式运行,如果当前存在事务,则抛出异常。

(7).PROPAGATION_NESTED
	a. 如果当前存在事务,则在嵌套事务中运行。嵌套事务可以保存为保存点,允许他回滚到保存点,而不影响外部事务。
	b. 方法A调用方法B,如果A在事务中,B将在A的嵌套事务中运行。如果B失败并回滚,他将回滚到嵌套事务的起始点,而不影响A的部分。

8. SpringMVC运行流程

  • SpringMVC 将所有的请求都提交给DispatcherServlet,他会委托应用系统的其他模块负责对请求进行真正的处理工作。
  • DispatcherServlet查询一个或者多个HandlerMapping,找到处理请求的Controller。
  • DispatcherServlet将请求提交到目标Controller。
  • Controller进行业务逻辑处理后,返回一个ModelAndView。
  • DispatcherServlet查询一个或者多个ViewResolver视图解析器,找到ModelAndView对象指定的视图对象。
  • 视图对象负责渲染返回给客户端。

9. SpringMVC启动流程

SpringMVC的启动是一个负责但是有序的过程,主要涉及Tomcat的启动、Spring容器的创建和初始化、以及DispatcherServlet的初始化与配置。以下是SpringMVC启动流程的详细步骤:

1. Tomcat启动
  Tomcat作为web容器,首先启动并读取web.xml文件,在web.xml文件中,
  会配置SpringMVC的前端控制器DispatcherServlet。

2. 解析web.xml文件
  Tomcat解析文件时,会识别到DispatcherServlet的配置,通常包括Servlet名称、类名以及初始化参数。

3. 创建DispatcherServlet对象
  根据web.xml中的配置,Tomcat会创建DispatcherServlet实例。

4. 初始化DispatcherServlet
  调用DispatcherServlet的init()方法,该方法会进一步执行SpringMVC的初始化逻辑。

5. 初始化Spring容器
  在DispatcherServlet的init()方法中,会创建一个Spring容器(WebApplicationContext),
  并加载SpringMVC的配置文件。其中定义了Spring MVC的Bean和配置信息。
 
 6. 注册并初始化组件
   DispatcherServlet会注册并初始化多个关键组件,包括
   a. HandlerMapping: 负责将请求映射到相应的处理器上。
   b. HandlerAdapter: 负责将请求适配到相应的处理器上。由于处理器可能有多种类型
     (如实现了Controller接口的Bean、实现了HttpRequestHandler接口的Bean、
      带有@RequestMapping注解的方法等),因此需要不同的HandlerAdapter来处理不同类型的处理器。
  c. ViewResolver: 负责将处理器返回的ModelAndView对象渲染成具体的视图。
  d. 其他组件:如MultipartResolver、LocaleResolver等。

 7. 监听器和事件
	在Spring容器启动过程中,会注册一个ContextRefreshListener监听器,当Spring容器创建完成时,
	会发布一个ContextRefreshEvent事件,该事件会被ContextRefreshListener捕获并处理,进而执
	行DispatcherServlet的initStrategies()方法,完成上述组件的初始化。

 8.  处理Http请求
	 初始化完成后,DispatcherServlet会监听HTTP请求,当有请求到达时,会根据请求的路径和类型,
	 通过HandlerMapping找到对应的处理器(Controller),然后通过HandlerAdapter调用处理器的
	 方法处理请求,处理完成后,将结果封装成ModelAndView对象,并交给ViewResolver进行渲染,
	 最终生成响应返回给客户端。


总结:SpringMVC的启动流程是一个从Tomcat启动到DispatcherServlet初始化,再到Spring容器创建和
组件注册的过程。这个过程中涉及多个关键组件的初始化和配置,以确保Spring MVC能够正确处理HTTP请求并
返回响应。

10. Spring的单例实现原理

 Spring对Bean的实例创建是采用单例注册表的方式进行实现的,而这个注册表的缓存是ConcurrentHashMap对象。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值