Spring高频面试题

1.什么是Spring框架?Spring框架有哪些主要模块?

​ 我们一般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发。这些模块是:核心容器、数据访问/集成,、Web、AOP(面向切面编程)、工具、消息和测试模块。

Spring模块图:
在这里插入图片描述

2…使用Spring框架能带来哪些好处?

  • 低侵入式设计,代码污染极低
  • Spring的DI机制降低了业务对象替换的复杂性
  • Spring并不完全依赖于Spring,开发者可自由选用Spring框架的部分或全部

3.什么是控制反转(IOC)?什么是依赖注入?

  • IOC是一种设计思想,就是将原本手动创建对象程序的控制权交给Spring,由Spring框架来管理对象来管理,IOC在其他对象中也有应用,并非是Spring特有。
  • DI是指将对象之间的依赖关系交给Spring容器去管理,组件之间的依赖关系由Spring容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

4.在Java中依赖注入有哪些方式?

  • setter、getter方法注入
  • 构造方法注入
  • 通过接口的方式注入(实例工厂的方法注入)

5.BeanFactory和ApplicationContext有什么区别?

功能方面
  • BeanFactory为Spring中最底层的接口,只包含各种bean的定义,读取bean配置文档,管理Bean加载、实例化、控制bean生命周期、维护bean之间的依赖关系。

  • ApplicationContext是Spring中更高级一层的接口,继承了BeanFactory接口,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能,例如:

    1.继承了MessageSource接口,提供了国际化的功能

    ​ 2.继承了ResourcePatternResolver接口,ResourcePatternResolver继承了ResourceLoader接口,提供了类或文件系统资源访问功能

    ​ 3.继承了ApplicationEventPublisher接口,提供了事件发布功能

  • BeanFactory在使用getBean时才去创建bean对象(懒加载方式)、ApplicationContext在加载配置文件时就去创建所有单实例bean对象(预加载方式)、

6.Spring提供几种配置方式来设置元数据?

什么是设置元数据:比如web项目中的Contrller层,Service层,Dao层均有想用的注解对应,在对应的类上加上诸如@Controller,@Service,@Repository,@Component的注解。

  • 基于XML的配置元数据
  • 基于注解的配置元数据(@Component、@Service、@Controller、@Repository等注解)
  • 基于Java的配置元数据。默认情况下,方法名就是Bean的名称。

7.如何使用XML配置的方式配置Spring?

Spring主要命名空间:Spring 有以下主要的命名空间:context、beans、jdbc、tx、aop、mvc 和 aso。
例如:

<beans>
<!-- JSON Support -->
<bean name="viewResolver"
class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
<bean name="jsonTemplate"
class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/>
</beans>

8.如何使用Java方式配置Spring?

Spring 对 Java 配置的支持是由@Configuration 注解和@Bean 注解来实现的。由@Bean 注解的方法将会实例化、配置和初始化一个新对象,这个对象将由 Spring 的 IOC 容器来管理。例如:

@Configuration
public class AppConfig{
	@Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

9. 怎样用注解的方式配置Spring

使用@Component、@Service、@Controller、@Repository等注解

10. 请解释Spring Bean的生命周期(重要)?

[外链图片转存失败(img-v0k82SeI-1566005951294)(G:\各种文档\图与笔记\笔记与博客\面试相关\assets\1565851103031.png)]

  • 首先容器启动后,对bean进行初始化
  • 按照bean的定义,注入属性
  • 检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给bean,如BeanNameAware等
  • 以上步骤,bean对象已正确构造,通过实现BeanPostProcessor接口,可以再进行一些自定义方法处理。如:postProcessBeforeInitialzation。
  • BeanPostProcessor的前置处理完成后,可以实现postConstruct,afterPropertiesSet,init-method等方法, 增加我们自定义的逻辑,
  • 通过实现BeanPostProcessor接口,进行postProcessAfterInitialzation后置处理
  • 接着Bean准备好被使用啦。
  • 容器关闭后,如果Bean实现了DisposableBean接口,则会回调该接口的destroy()方法
  • 通过给destroy-method指定函数,就可以在bean销毁前执行指定的逻辑

11.Spring Bean作用域的区别是什么?

  • singleton:单例范围,这种bean范围是默认的,不管有多少个请求,IOC容器中只会有一个bean的实例
  • prototype:原形范围,为每一个bean请求创建一个bean实例
  • request:在请求 bean 范围内会每一个来自客户端的网络请求创建一个实例,在请求完成以后,bean 会失效并被垃圾回收器回收。
  • session:与request类似,确保每一个会话中只有一个相同bean实例
  • global-session:global-session 和 Portlet 应用相关。当你的应用部署在 Portlet 容器中作时,它包含很多 portlet。如果你想要声明让所有的 portlet 共用全局的存储变量的话,那么这全局变量需要存储在 global-session 中。全局作用域与 Servlet 中的 session 作用域效果相同。

12.什么是Spring Inner Bean

有点类似于java的内部类,当希望一个bean只被某一个类使用时,我们可以使用内部bean。内部bean此时作为某一个类的属性,只能通过该类的setter或者构造器实例化。
例如:希望Sun类只内Father类使用,只有实例化Father类才能实例化Sun类

public class Father {
    private Sun sun;
}
<bean id="Father" class="xxx.Father">
        <property name="sun">
            <bean class="xxx.Sun"> </bean>           
        </property>
    </bean>

13.Spring框架中的单例Bean是线程安全的吗?

不安全,一般来说线程安全问题都是由全局变量及静态变量引起的。
解决办法:
1.使用ThreadLocal,为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。
2.改用singleton范围的,每次都创建一个新的实例bean(不推荐)
一个比较不错讲解单例线程问题的文章:https://segmentfault.com/a/1190000016763039

14.请解释Spring Bean的自动装配?

自动装配是指Spring容器可以动态装配Bean之间的依赖关系,(简单理解为依赖注入)

15.自动装配的局限性

  • 重写:你仍然需要使用@Autowrite 和< property>设置指明依赖,这意味着总要重写自动装配。
  • 原生数据类型:你不能自动装配简单的属性,如原生类型、字符串和类。
  • 模糊特性:自动装配总是没有自定义装配精确,因此,如果可能尽量使用自定义装配。

16.请解释各种自动装配模式的区别?

  • no:这是Spring框架的默认设置,在该设置下自动装配是关闭的,开发者需要自行在bean定义中用标签明确的设置依赖关系。
  • byName:该选项可以根据bean名称设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的名称自动在在配置文件中查询一个匹配的bean。如果找到的话,就装配这个属性,如果没找到的话就报错。
  • byType:该选项可以根据bean类型设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的类型自动在在配置文件中查询一个匹配的bean。如果找到的话,就装配这个属性,如果没找到的话就报错。
  • constructor:造器的自动装配和byType模式类似,但是仅仅适用于与有构造器相同参数的bean,如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。
  • autodetect:该模式自动探测使用构造器自动装配或者byType自动装配。首先,首先会尝试找合适的带参数的构造器,如果找到的话就是用构造器自动装配,如果在bean内部没有找到相应的构造器或者是无参构造器,容器就会自动选择byTpe的自动装配方式。
    现在@Autowired注解是默认使用byType方式,可以搭配@Qualifier使用byName装配方式

17. 请举例解释@Required Annotation?

@Required只能注解在方法上,主要注解在Setter方法上,用于检查属性是否注入进去了(也就是必须注入进去)。
例如:如果在Customer注入到Spring中,没有将person注入进去就会报错BeanInitializationException

 public class Customer {
     private Person person;
     
    @Required
	public void setPerson(Person person) {
		this.person = person;
	}
     
 }

18. Spring框架中有哪些不同类型的事件?

  • 上下文更新事件(ContextRefreshedEvent):在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
  • 上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
  • 上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
  • 上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
  • 请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。
  • 如果一个bean实现了ApplicationListener接口,当一个ApplicationEvent 被发布以后,bean会自动被通知。

19.FileSystemResource和ClassPathResource有何区别

在 FileSystemResource 中需要给出 spring-config.xml 文件在你项目中的相对路径或者绝对路径。在 ClassPathResource 中 spring 会在 ClassPath 中自动搜寻配置文件,所以要ClassPathResource 文件放在 ClassPath 下。如果将 spring-config.xml 保存在了 src 文件夹下的话,只需给出配置文件的名称即可,因为 src文件夹是默认。简而言之,ClassPathResource 在环境变量中读取配置文件FileSystemResource 在配置文件中读取配置文件。

20.Spring 框架中都用到了哪些设计模式?

工厂设计模式
Spring使用工厂模式可以通过 BeanFactory 或 ApplicationContext 创建 bean 对象。
单例设计模式
简单说一下单例模式的好处:
1.对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级对象而言,是非常可观的一笔系统开销;
2.由于 new 操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻 GC 压力,缩短 GC 停顿时间。
代理设计模式

Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用Cglib ,这时候Spring AOP会使用 Cglib 生成一个被代理对象的子类来作为代理

模板方法模式

模板方法模式是一种行为设计模式,它定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤的实现方式。
代码演示:


public abstract class Template {
    //这是我们的模板方法
    public final void TemplateMethod(){
        PrimitiveOperation1();  
        PrimitiveOperation2();
        PrimitiveOperation3();
    }

    protected void  PrimitiveOperation1(){
        //当前类实现
    }

    //被子类实现的方法
    protected abstract void PrimitiveOperation2();
    protected abstract void PrimitiveOperation3();

}
public class TemplateImpl extends Template {

    @Override
    public void PrimitiveOperation2() {
        //当前类实现
    }

    @Override
    public void PrimitiveOperation3() {
        //当前类实现
    }
}

Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。但是spring中的JdbcTemplate并没有用到模板模式的继承方式。而是用Callback方式做去完成调用的。

观察者模式

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。spring中Observer模式常用的地方是listener的实现。如ApplicationListener。
在这里插入图片描述

适配器模式

我们知道 Spring AOP 的实现是基于代理模式,但是 Spring AOP 的增强或通知(Advice)使用到了适配器模式,与之相关的接口是AdvisorAdapter 。Advice 常用的类型有:BeforeAdvice(目标方法调用前,前置通知)、AfterAdvice(目标方法调用后,后置通知)、AfterReturningAdvice(目标方法执行结束后,return之前)等等。每个类型Advice(通知)都有对应的拦截器:MethodBeforeAdviceInterceptor、AfterReturningAdviceAdapter、AfterReturningAdviceInterceptor。Spring预定义的通知要通过对应的适配器,适配成 MethodInterceptor接口(方法拦截器)类型的对象(如:MethodBeforeAdviceInterceptor 负责适配 MethodBeforeAdvice)。
在这里插入图片描述

21.在Spring框架中如何更有效地使用JDBC?

使用Spring JDBC框架,资源管理以及错误处理的代价都会减轻。开发人员只需通过statements和 sql 语句从数据库中存取数据。Spring 框架中通过使用模板类能更有效的使用 JDBC,也就是所谓的 JdbcTemplate。

22. 在Spring中可以注入null或空字符串吗?

可以。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值