Spring面试题

Spring

1. @Value 注解的作用是什么?

答:基于 @Value 的注解可以读取 properties 配置文件,使用如下:

2. Spring 通知类型有哪些?

答:Spring 通知类型总共有 5 种:前置通知、环绕通知、后置通知、异常通知、最终通知。

  • 前置通知(Before advice):在目标方法执行之前执行的通知。在某连接点( join point )之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。
  • 环绕通知(Around Advice):在目标方法执行之前和之后都可以执行额外代码的通知,也可以选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。
  • 后置通知(After (finally) advice):目标方法执行之后(某连接点退出的时候)执行的通知(不论是正常返回还是异常退出)。
  • 异常后通知(After throwing advice):在方法抛出异常退出时执行的通知。
  • 最终通知(After returning advice):在某连接点(join point)正常完成后执行的通知,例如,一个方法没有抛出任何异常,正常返回。

3. 怎么理解 Spring 中的 IOC 容器?

答:Spring IOC 就是把创建对象的权利交给框架去控制,而不需要人为的去创建,这样就实现了可插拔式的接口编程,有效地降低代码的耦合度,降低了扩展和维护的成本。

比如,去某地旅游不再用自己亲自为订购 A 酒店还是 B 酒店而发愁了,只需要把住店的需求告诉给某个托管平台,这个托管平台就会帮你订购一个既便宜又舒适的酒店,而这个帮你订购酒店的行为就可以称之为控制反转。

4. 怎么理解 Spring 中的依赖注入?

答:依赖注入是指组件之间的依赖关系由容器在运行期决定,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

5. IoC 和 DI 有什么关系?

答:IoC 是 Spring 中一个极为重要的概念,提供了对象管理的功能,从而省去了人为创建麻烦,而 DI 正是实现 IoC 的方法和手段。

6. @Component 和 @Bean 有什么区别?

答:它们的作用对象不同:

  • @Component 作用于类;
  • @Bean 注解作用于方法。

@Component 通常是通过类路径扫描来自动侦测和装配对象到 Spring 容器中,比如 @ComponentScan 注解就是定义扫描路径中的类装配到 Spring 的 Bean 容器中;

@Bean 注解是告诉 Spring 这是某个类的实例,当我需要用它的时把它给我,@Bean 注解比 @Component 注解自定义性更强,很多地方我们只能通过 @Bean 注解来注册 Bean,比如当我们引用第三方库中的类需要装配到 Spring容器时,则只能通过 @Bean 来实现,比如以下示例,只能通过 @Bean 注解来实现:

public class WireThirdLibClass {
    @Bean
    public ThirdLibClass getThirdLibClass() {
        return new ThirdLibClass();
}
}=

7. Spring 中 bean 的作用域有几种类型?

答:Spring 中 bean 的作用域有四种类型,如下列表:

  • 单例(Singleton):整个应用程序,只创建 bean 的一个实例;
  • 原型(Prototype):每次注入都会创建一个新的 bean 实例;
  • 会话(Session):每个会话创建一个 bean 实例,只在 Web 系统中有效;
  • 请求(Request):每个请求创建一个 bean 实例,只在 Web 系统中有效。

Spring 默认的是单例模式。

8. 什么是 Spring 的内部 bean?

答:当一个 bean 仅被用作另一个 bean 的属性时,它能被声明为一个内部 bean,为了定义 inner Bean,在 Spring 的基于 XML 的配置元数据中,可以在 <property/><constructor-arg/> 元素内使用 <bean/> 元素,内部 bean 通常是匿名的,它们的 Scope 一般是 prototype 。

9. Spring 注入方式有哪些?

答:Spring 的注入方式包含以下五种:

  • setter 注入
  • 构造方法注入
  • 注解注入
  • 静态工厂注入
  • 1实例工厂注入

其中最常用的是前三种,官方推荐使用的是注解注入,相对使用更简单,维护成本更低,更直观。

10. 在 Spring 中如何操作数据库?

答:在 Spring 中操作数据库,可以使用 Spring 提供的 JdbcTemplate 对象,JdbcTemplate 类提供了很多便利的方法,比如把数据库数据转变成基本数据类型或对象,执行自定义的 SQL 语句,提供了自定义的数据错误处理等,JdbcTemplate 使用示例如下:

@Autowired
private JdbcTemplate jdbcTemplate;

// 新增
@GetMapping("save")
public String save() {
    String sql = "INSERT INTO USER (USER_NAME,PASS_WORD) VALUES ('laowang','123')";
    int rows = jdbcTemplate.update(sql);
    return "执行成功,影响" + rows + "行";
}

// 删除
@GetMapping("del")
public String del(int id) {
    int rows= jdbcTemplate.update("DELETE FROM  USER  WHERE ID = ?",id);
    return "执行成功,影响" + rows + "行";
}

// 查询
@GetMapping("getMapById")
public Map getMapById(Integer id) {
    String sql = "SELECT * FROM USER WHERE ID = ?";
    Map map= jdbcTemplate.queryForMap(sql,id);
    return map;
}Copy to clipboardErrorCopied

11. Spring 的 JdbcTemplate 对象和 JDBC 有什么区别?

答:Spring 的 JdbcTemplate 是对 JDBC API 的封装,提供更多的功能和更便利的操作,比如 JdbcTemplate 拥有:

  • JdbcTemplate 是线程安全的;
  • 实例化操作比较简单,仅需要传递 DataSource;
  • 自动完成资源的创建和释放工作;
  • 创建一次 JdbcTemplate,到处可用,避免重复开发。

12. Spring 有几种实现事务的方式?

答:Spring 实现事务有两种方式:编程式事务和声明式事务。

编程式事务,使用 TransactionTemplate 或 PlatformTransactionManager 实现,示例代码如下:

private final TransactionTemplate transactionTemplate;

public void add(User user) throws Exception{
    // Spring编码式事务,回调机制
    transactionTemplate.execute(new TransactionCallback<Object>() {
        @Override
        public Object doInTransaction(TransactionStatus status) {
            try {
                userMapper.insertSelective(user);
            } catch (Exception e) {
                // 异常,设置为回滚
                status.setRollbackOnly();
                throw e;
            }
            return null;
        }
    });
}

如果有异常,调用 status.setRollbackOnly() 回滚事务,否则正常执行 doInTransaction() 方法,正常提交事务。

如果事务控制的方法不需要返回值,就可以使用 TransactionCallbackWithoutResult(TransactionCallback 接口的抽象实现类)示例代码如下:

public void add(User user) throws Exception {
    // Spring编码式事务,回调机制
    transactionTemplate.execute(new TransactionCallbackWithoutResult() {
        @Override
        protected void doInTransactionWithoutResult(TransactionStatus status) {
            try {
                userMapper.insertSelective(user);
            } catch (Exception e) {
            // 异常,设置为回滚
            status.setRollbackOnly();
                throw e;
            }
        }
    });
}Copy to clipboardErrorCopied

声明式事务,底层是建立在 Spring AOP 的基础上,在方式执行前后进行拦截,并在目标方法开始执行前创建新事务或加入一个已存在事务,最后在目标方法执行完后根据情况提交或者回滚事务。

声明式事务的优点:不需要编程,减少了代码的耦合,在配置文件中配置并在目标方法上添加 @Transactional 注解来实现,示例代码如下:

@Transactional
public void save() {
    User user = new User("laowang");
    userMapper.insertSelective(user);
    if (true) {
        throw new RuntimeException("异常");
    }
}

抛出异常,事务会自动回滚,如果方法正常执行,则会自动提交事务。

13. Spring 事务隔离级别有哪些?

答:Spring 的注入方式包含以下五种:

  • ISOLATION_DEFAULT:用底层数据库的设置隔离级别,数据库设置的是什么我就用什么;
  • ISOLATIONREADUNCOMMITTED:未提交读,最低隔离级别、事务未提交前,就可被其他事务读取(会出现幻读、脏读、不可重复读);
  • ISOLATIONREADCOMMITTED:提交读,一个事务提交后才能被其他事务读取到(会造成幻读、不可重复读),SQL server 的默认级别;
  • ISOLATIONREPEATABLEREAD:可重复读,保证多次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(会造成幻读),MySQL 的默认级别;
  • ISOLATION_SERIALIZABLE:序列化,代价最高最可靠的隔离级别,该隔离级别能防止脏读、不可重复读、幻读。

默认值为 ISOLATION_DEFAULT 遵循数据库的事务隔离级别设置。

14. Spring 声明式事务无效可能的原因有哪些?

答:可能的原因如下:

  • MySQL 使用的是 MyISAM 引擎,而 MyISAM 是不支持事务的;
  • @Transactional 使用在非 public 方法上,@Transactional 注解只能支持 public 级别,其他类型声明的事务不会生效;
  • @Transactional 在同一个类中无事务方法 A() 内部调用有事务方法 B(),那么此时 B() 事物不会生效。

15. Spring 中的 AOP 的底层实现原理是什么?

答:Spring AOP 的底层实现原理就是动态代理。

Spring AOP 的动态代理有两种实现方式,对于接口使用的是 JDK 自带的动态代理来实现的,而对比非接口使用的是 CGLib 来实现的。

16. Spring 中的 Bean 是线程安全的吗?

答:Spring 中的 Bean 默认是单例模式,Spring 框架并没有对单例 Bean 进行多线程的封装处理,因此默认的情况 Bean 并非是安全的,最简单保证 Bean 安全的举措就是设置 Bean 的作用域为 Prototype(原型)模式,这样每次请求都会新建一个 Bean 。

17. 说一下 Spring 中 Bean 的生命周期?

Spring Bean的完整生命周期从创建Spring容器开始,直到最终Spring容器销毁Bean

1.通过BeanDefinition接口得到类的信息
2.如果有多个构造方法,则要推析构造方法
3.确定好构造方法后,进行实外化得到一个对象
4.对对象中的属性加了@Autowired注解的进行注值
5.回调aware方法,如BeanNameAware, BeanFactoryAware
6.如果想对 Bean 进行一些自定义的处理,那么可以让 Bean 实现了 BeanPostProcessor 接口,重写postProcessBeforeInitialization(该方法在bean初始化方法调用前被调用)和postProcessAfterInitialization方法(bean初始化方法调用后被调用),例如:我们可以修改bean的属性,可以给bean生成一个动态代理实例
7.继承InitializingBean接口,凡是继承该接口的类,在初始化bean的时候都会执行该方法afterPropertiesSet()

8.調用BeanPostProcessor的机始化后的万法, 在这里会进行AOP
9.如果当前创建的bean是单例的则会把bean放入单例池
10.使用bean
11. Spring容器关闭时调用DisposableBean接口的destory()方法,如果这个 Bean 的 Spring 配置中配置了 destroy-method 属性,会自动调用其配置的销毁方法。

18.Spring 有哪些优点?

答:Spring 优点如下:

  • 开源免费的热门框架,稳定性高、解决问题成本低;
  • 方便集成各种优秀的框架;
  • 降低了代码耦合性,通过 Spring 提供的 IoC 容器,我们可以将对象之间的依赖关系交由 Spring 进行控制,避免硬编码所造成的过度程序耦合;
  • 方便程序测试,在 Spring 里,测试变得非常简单,例如:Spring 对 Junit 的支持,可以通过注解方便的测试 Spring 程序;
  • 降低 Java EE API 的使用难度,Spring 对很多难用的 Java EE API(如 JDBC、JavaMail、远程调用等)提供了一层封装,通过 Spring 的简易封装,让这些 Java EE API 的使用难度大为降低。

19.Spring、SpringBoot、SpringCloud 的区别是什么?

答:它们的区别如下:

  • Spring Framework 简称 Spring,是整个 Spring 生态的基础。
  • Spring Boot 是一个快速开发框架,让开发者可以迅速搭建一套基于 Spring 的应用程序,并且将常用的 Spring 模块以及第三方模块,如 MyBatis、Hibernate 等都做了很好的集成,只需要简单的配置即可使用,不需要任何的 XML 配置文件,真正做到了开箱即用,同时默认支持 JSON 格式的数据,使用 Spring Boot 进行前后端分离开发也非常便捷。
  • Spring Cloud 是一套整合了分布式应用常用模块的框架,使得开发者可以快速实现微服务应用。作为目前非常热门的技术,有关微服务的话题总是在各种场景下被大家讨论,企业的招聘信息中也越来越多地出现对于微服务架构能力的要求。

20.Spring 中都是用了哪些设计模式?

答:Spring 中使用的设计模式如下:

  • 工厂模式:通过 BeanFactory、ApplicationContext 来创建 bean 都是属于工厂模式;
  • 单例、原型模式:创建 bean 对象设置作用域时,就可以声明 Singleton(单例模式)、Prototype(原型模式);
  • 观察者模式:Spring 可以定义一下监听,如 ApplicationListener 当某个动作触发时就会发出通知;
  • 责任链模式:AOP 拦截器的执行;
  • 代理模式:在创建代理类时,如果代理的是接口使用的是 JDK 自身的动态代理,如果不是接口使用的是 CGLIB 实现动态代理。

21.spring中的BeanFactory和FactoryBean区别?

  • BeanFactory:该接口是IoC容器的顶级接口,是IoC容器的最基础实现,也是访问Spring容器的根接口,负责对bean的创建,访问等工作
  • FactoryBean:是一种工厂bean,可以返回bean的实例,我们可以通过实现该接口对bean进行额外的操作,例如根据不同的配置类型返回不同类型的bean—参考构建bean的过程
Mybatis扫描到的@Mapper接口的Bean,存放到BeandefinitionMap里面的时候会关联上一个MapperFactoryBean.class,然后实例化的时候都是通过MapperFactoryBean.class去实例化,里面就通过动态代理创建出代理对象

22、spring常用的注解有哪些?

答:

1、用于创建对象的注解
作用:和在xml配置文件中编写一个标签实现的功能一样。

1.@Component : 用于把当前类对象存入Spring容器中。
  属性:value --- 用于指定bean的id。如果不写该属性,id的默认值是当前类名,且首字母改为小写。
2.@Controller : 一般用在表现层。
  @RestController
3.@Service : 一般用在业务层。
4.@Repository : 一般用在持久层(dto层) 

2、用于注入数据的注解

​ 作用:和在xml配置文件中的标签中写一个标签的功能一样。

1.@Autowired:自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。可以作用在变量或者方法上
2.@Qualifier: 在按照类型注入的基础之上再按照名称注入,它在给类成员注入时要和@Autowired配合使用,但是在给方法参数注入是可以单独使用。
3.@Resource : 直接按照bean的id注入,可以独立使用。

3、用于改变作用范围的注解

​ 作用:和在xml配置文件中的标签中使用scope属性实现的功能一样。

@Scope : 用于指定bean的作用范围。

4、和生命周期相关的注解

​ 作用:和在xml配置文件中的标签中使用init-method和destory-method属性实现的功能一样。

@PreDestory : 用于指定销毁方法。
@PostConstruct : 用于指定初始化方法。

5、Spring新注解

@Configuration : 用于指定当前类是一个配置类。
@ComponentScan : 用于通过注解指定Spring在创建容器时要扫描的包。
@Bean : 用于把当前方法的返回值作为bean对象存入Spring的IOC容器中。
	属性:name --- 用于指定bean的id。当不写时,默认值为当前方法的名称。
@Import : 用于导入其他的配置类。
@PropertySource : 用于指定properties文件的位置
@Value

23、BeanFactory和applicationContext区别

答:

1、描述:

BeanFactory:是Spring里面最顶层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能;

ApplicationContext:应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能

2、两者装载bean的区别:

BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化即延迟实例化

ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化;

3、使用场景:

BeanFactory延迟实例化的优点:

应用启动的时候占用资源很少;对资源要求较高的应用,比较有优势;

ApplicationContext立即实例化的有点

  1. 所有的Bean在启动的时候都加载,系统运行的速度快;

  2. 在启动的时候所有的Bean都加载了,我们就能在系统启动的时候,尽早的发现系统中的配置问题

  3. 建议web应用,在启动的时候就把所有的Bean都加载了。(把费时的操作放到系统启动中完成)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值