1. 什么是 Spring 框架?Spring 框架有哪些主要模块?
轻量级实现IoC和AOP的JavaEE框架。
Core模块:
bean(bean定义创建解析), context(环境, IoC容器), core(核心组件, util, 定义资源访问方式)。
Data模块:JDBC, ORM, OXM, JMS, Transactions
Web模块:WebMVC, WebFlux
AOP模块,Messaging模块(集成messaging API和消息协议提供支持)
2.使用 Spring 框架能带来哪些好处?
IoC,DI,AOP,MVC, 解耦,非入侵
3. 什么是控制反转(IOC)?什么是依赖注入?
IOC:Spring负责bean的生命周期管理。
DI: bean之间的依赖关系由Spring管理。
三种注入方式:
- 构造器注入
- Setter 方法注入
- 接口注入
4.请解释下 Spring 框架中的 IoC?
IOC:Spring负责bean的生命周期管理。
主要是指BeanFactory和ApplicationContext。
5.BeanFactory 和 ApplicationContext 有什么区别?
BeanFactory,Spring工厂方法的顶级接口。
ApplicationContext继承BeanFactory,包括全部功能,还扩展国际化,支持AOP, Web, 事件监听等。
6.Spring 有几种配置方式?
- XML
- 注解
- JavaConfig
7. 如何用基于 XML 配置的方式配置 Spring?
通过bean.xml配置文件。例如,XML中配置一个user bean。
<bean id=“user”class=”com.xxx.User”>
代码里通过applicatoinContext是创建bean,获取bean。
ApplicationContext context = new ClasspathApplicationContext(“bean.xml”);
User user = context.getBean(“user”);
8.如何用基于 Java 配置的方式配置 Spring?
定义一个Config组件类,类标注@Configuration,相等于XML, 里面方法标注@bean表示该返回对象是一个bean放入Spring IoC。
@ComponentScan组件扫描配置的Config类。
9. 怎样用注解的方式配置 Spring?
@Component,@Controller @Repository, @Service 标识类。
10.请解释 Spring Bean 的生命周期?
1. 实例化Bean(new)
2. 填充属性
3.检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给bean。
4.是否实现BeanPostProcessor接口, 前置处理方法postProcessBeforeInitialization
5. 检查是否实现InitializatingBean接口,实现调用afterPropertiesSet()方法,与在XML配置init-method作用一致。
6.后置方法postProcessAfterinitialzation()。
Bean将驻留在应用上下文给应用使用。
销毁流程1. 如果实现DisposableBean,调用destroy方法,和XML配置destroy-method一致。
11. Spring Bean 的作用域之间有什么区别?
singleton, prototype, request, session
spring5: application, websocket分别保证在一个ServletContext和一个WebSocket中只创建一个实例。
12. 什么是 Spring inner beans?
有点像Java内部类。如果一个bean只在另一个bean中依赖,在可以定义为spring inner bean。
例如:peson是customer的spring inner bean.
<?xml version="1.0"?>
<bean id="CustomerBean" class="com.mkyong.common.Customer">
<property name="person">
<bean class="com.mkyong.common.Person">
<property name="name" value="mkyong" />
<property name="address" value="address1" />
<property name="age" value="28" />
</bean>
</property>
</bean>
</beans>
注意,id和name在inner bean中不是必须的,因为会被spring容器忽略。
13. Spring 框架中的单例 Beans 是线程安全的么?
不是线程安全的。需要开发者自己解决线程安全问题。Spring管理大多数对手是无状态对象。单例的无状态对象是线程安全的。
14.请举例说明如何在 Spring 中注入一个 Java Collection?
1. Spring提供4种集合类的配置元素:<list>,<set>,<map>,<props>
XML:注入list
<property>
<list>
<value>A</value>
<value>B</value>
</list>
</property>
2. 用@Value读取propeties作为map或list注入。
16.请解释 Spring Bean 的自动装配?自动装配好处?
装配就是创建对象之间的依赖,注入依赖的属性。
自动装配就是自动注入依赖,是相对于之前用XML文件来手动注入。
好处是减少消除<property>,<constructor-arg>元素,减少XML配置。
1.组件扫描,Spring会自动发现应用上下文中所创建的bean。2.Spring满足bean直接的依赖关系。
17.请解释自动装配模式的区别?
5种。
no: 默认设置,自动装配是关闭的,开发者自行设置依赖关系。
byName:根据bean的名字和当前bean 的setter风格的属性名进行自动装配,若有匹配的,则进行自动装配,若没有,则不匹配
byType:根据bean 的类型和当前bean的属性的类型进行自动装配,若IOC容器中有一个以上的类型匹配的bean,则抛异常
constructor:适用于与有构造器相同参数的bean,如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。
autodetect:自动探测使用构造器自动装配或者byType自动装配。
18.如何开启基于注解的自动装配?
XML配置文件情况下:
<beans>
<context:annotation-config />
</beans>
Springboot,直接用:
@Autowired、@Qualifier、@Resource
@Resource为sun公司提供的注解,也可以使用与属性和方法上,在自动装配时默认使用装配类的首字母小写的字符串去容器中查找实例进行装配。
19. 请举例解释@Required 注解?
@Required注解作用于Bean的setter方法上,用于检查一个Bean的属性的值在配置期间是否被赋予或设置(populated)
20.请举例解释@Autowired 注解?
@Autowired在默认情况下是必须进行装配,如果没有装配成功会报错可以通过设置
@Autowired(required = false)来让自动装配没有成功时不进行自动装配
21. 请举例说明@Qualifier 注解?
@Qualifier一般与@Autowired搭配使用,作用为在spring容器中通过类进行查找的同时会通过spring中配置的bean的id进行查找
22.构造方法注入和设值注入有什么区别?
XML配置中:在xml文件下对应使用property和constructor-arg属性。
构造:适用于强依赖关联。
设值:适用于弱依赖。(Spring可以解决循环依赖)
23.Spring 框架中有哪些不同类型的事件?
Spring 的 ApplicationContext 提供了支持事件和代码中监听器的功能。
可以创建 bean 用来监听在 ApplicationContext 中发布的事件。ApplicationEvent 类和在 ApplicationContext 接口中处理的事件,如果一个 bean 实现了 ApplicationListener 接口,当一个 ApplicationEvent 被发布以后,bean 会自动被通知。
Spring 提供了以下 5 中标准的事件:
1.上下文更新事件(ContextRefreshedEvent):该事件会在 ApplicationContext 被初始化或者更新时发布。也可以在调用 ConfigurableApplicationContext 接口中的 refresh()方法时被触发。
2.上下文开始事件(ContextStartedEvent):当容器调用 ConfigurableApplicationContext的 Start()方法开始/重新开始容器时触发该事件。
3.上下文停止事件(ContextStoppedEvent):当容器调用 ConfigurableApplicationContext的 Stop()方法停止容器时触发该事件。
4.上下文关闭事件(ContextClosedEvent):当 ApplicationContext 被关闭时触发该事件。容器被关闭时,其管理的所有单例 Bean 都被销毁。
5.请求处理事件(RequestHandledEvent):在 Web 应用中,当一个 http 请求(request)结束触发该事件。
除了上面介绍的事件以外,还可以通过扩展 ApplicationEvent 类来开发自定义的事件。
Spring 的事件流程总结:
定义一个事件: 实现一个继承自 ApplicationEvent,并且写相应的构造函数;
定义一个事件监听者:实现 ApplicationListener 接口,重写 onApplicationEvent() 方法;
使用事件发布者发布消息: 可以通过 ApplicationEventPublisher 的 publishEvent() 方法发布消息。
24.FileSystemResource 和 ClassPathResource 有何区别?
ClassPathResource在环境变量中读取配置文件,FileSystemResource在配置文件中读取配置文件
5种获取资源类的区别:
ClassPathResource:从系统的类路径中加载
FileSystemResource:从文件系统加载,比如说自己指定配置文件的全路径
InputStreamResource:从输入流中加载
ServletContextResource:从Servlet 上下文环境中加载
UrlResource:从指定的Url加载
25. Spring 框架中都用到了哪些设计模式?
工厂模式:
BeanFactory和ApplicationContext:简单工厂模式,实质是由一个工厂类根据传入的参数(beanId),动态决定应该创建哪一个产品类。
FactoryBean:工厂方法模式,工厂方法模式就是一个工厂接口和多个工厂实现类,要增加一个新的产品,增加一个新的工厂实现类即可,针对之前的老的工厂实现类也不需要修改。
单例模式:
Spring 中 bean 的默认作用域就是 singleton(单例)。
Spring 通过 ConcurrentHashMap 实现单例注册表的特殊方式实现单例模式。
代理设计模式:
Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用Cglib ,这时候Spring AOP会使用 Cglib 生成一个被代理对象的子类来作为代理。
模板方法模式:
模板方法模式是一种行为设计模式,它定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤的实现方式。
Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。
观察者模式:
观察者模式是一种对象行为型模式。它表示的是一种对象与对象之间具有依赖关系,当一个对象发生改变的时候,这个对象所依赖的对象也会做出反应。
Spring 事件驱动模型就是观察者模式很经典的一个应用。Spring 事件驱动模型非常有用,在很多场景都可以解耦我们的代码。比如我们每次添加商品的时候都需要重新更新商品索引,这个时候就可以利用观察者模式来解决这个问题。
适配器模式:
适配器模式(Adapter Pattern) 将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。
SpringAOP:
Spring AOP 的增强或通知(Advice)使用到了适配器模式,与之相关的接口是AdvisorAdapter 。Advice 常用的类型有:BeforeAdvice(目标方法调用前,前置通知)、AfterAdvice(目标方法调用后,后置通知)、AfterReturningAdvice(目标方法执行结束后,return之前)等等。每个类型Advice(通知)都有对应的拦截器:MethodBeforeAdviceInterceptor、AfterReturningAdviceAdapter、AfterReturningAdviceInterceptor。Spring预定义的通知要通过对应的适配器,适配成 MethodInterceptor接口(方法拦截器)类型的对象(如:MethodBeforeAdviceInterceptor 负责适配 MethodBeforeAdvice)。
SpringMVC:
DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由HandlerAdapter 适配器处理。HandlerAdapter 作为期望接口,具体的适配器实现类用于对目标类进行适配,Controller 作为需要适配的类。
装饰者模式:
装饰者模式可以动态地给对象添加一些额外的属性或行为。相比于使用继承,装饰者模式更加灵活。简单点儿说就是当我们需要修改原有的功能,但我们又不愿直接去修改原有的代码时,设计一个Decorator套在原有代码外面。
其实在 JDK 中就有很多地方用到了装饰者模式,比如 InputStream家族,InputStream 类下有 FileInputStream (读取文件)、BufferedInputStream (增加缓存,使读取文件速度大大提升)等子类都在不修改InputStream 代码的情况下扩展了它的功能。
Spring 中配置 DataSource 的时候,DataSource 可能是不同的数据库和数据源。Spring 中用到的包装器模式在类名上含有 Wrapper或者 Decorator。这些类基本上都是动态地给一个对象添加一些额外的职责。
参考: