准备了一个月的八股文,经历了二十几场面试之后,发现Spring很受面试官青睐。最近有空将Spring常见的面试题总结了一下,希望对大家有所帮助。
文章目录:
- Spring的优点
- Spring 用到了哪些设计模式?
- 什么是AOP?
- AOP有哪些实现方式?
- JDK动态代理和CGLIB动态代理的区别?
- Spring AOP相关术语
- Spring通知有哪些类型?
- 什么是IOC?
- IOC的优点是什么?
- 什么是依赖注入?
- IOC容器初始化过程?
- Bean的生命周期
- BeanFactory和FactoryBean的区别?
- Bean注入容器有哪些方式?
- Bean的作用域
- Spring自动装配的方式有哪些?
- @Autowired和@Resource的区别?
- @Qualifier 注解有什么作用
- @Bean和@Component有什么区别?
- @Component、@Controller、@Repositor和@Service 的区别?
- Spring 事务实现方式有哪些?
- 有哪些事务传播行为?
- Spring怎么解决循环依赖的问题?
- Spring启动过程
- Spring 的单例 Bean 是否有线程安全问题?
Spring的优点
- 轻量,基本版本大约2MB。
- 通过控制反转和依赖注入实现松耦合。
- 支持面向切面的编程,并且把应用业务逻辑和系统服务分开。
- 通过切面和模板减少样板式代码。
- 方便集成各种优秀框架。内部提供了对各种优秀框架的直接支持(如:Hibernate、MyBatis等)。
- 方便程序的测试。Spring支持Junit4,添加注解便可以测试Spring程序。
Spring 用到了哪些设计模式?
1、简单工厂模式:BeanFactory
就是简单工厂模式的体现,根据传入一个唯一标识来获得 Bean 对象。
@Override
public Object getBean(String name) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name);
}
2、工厂方法模式:FactoryBean
就是典型的工厂方法模式。spring在使用getBean()
调用获得该bean时,会自动调用该bean的getObject()
方法。每个 Bean 都会对应一个 FactoryBean
,如 SqlSessionFactory
对应 SqlSessionFactoryBean
。
3、单例模式:一个类仅有一个实例,提供一个访问它的全局访问点。Spring 创建 Bean 实例默认是单例的。
4、适配器模式:SpringMVC中的适配器HandlerAdatper
。由于应用会有多个Controller实现,如果需要直接调用Controller方法,那么需要先判断是由哪一个Controller处理请求,然后调用相应的方法。当增加新的 Controller,需要修改原来的逻辑,违反了开闭原则(对修改关闭,对扩展开放)。
为此,Spring提供了一个适配器接口,每一种 Controller 对应一种 HandlerAdapter
实现类,当请求过来,SpringMVC会调用getHandler()
获取相应的Controller,然后获取该Controller对应的 HandlerAdapter
,最后调用HandlerAdapter
的handle()
方法处理请求,实际上调用的是Controller的handleRequest()
。每次添加新的 Controller 时,只需要增加一个适配器类就可以,无需修改原有的逻辑。
常用的处理器适配器:SimpleControllerHandlerAdapter
,HttpRequestHandlerAdapter
,AnnotationMethodHandlerAdapter
。
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
public class HttpRequestHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {//handler是被适配的对象,这里使用的是对象的适配器模式
return (handler instanceof HttpRequestHandler);
}
@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
((HttpRequestHandler) handler).handleRequest(request, response);
return null;
}
}
5、代理模式:spring 的 aop 使用了动态代理,有两种方式JdkDynamicAopProxy
和Cglib2AopProxy
。
6、观察者模式:spring 中 observer 模式常用的地方是 listener 的实现,如ApplicationListener
。
7、模板模式: Spring 中 jdbcTemplate
、hibernateTemplate
等,就使用到了模板模式。
什么是AOP?
面向切面编程,作为面向对象的一种补充,将公共逻辑(事务管理、日志、缓存等)封装成切面,跟业务代码进行分离,可以减少系统的重复代码和降低模块之间的耦合度。切面就是那些与业务无关,但所有业务模块都会调用的公共逻辑。
AOP有哪些实现方式?
AOP有两种实现方式:静态代理和动态代理。
静态代理
静态代理:代理类在编译阶段生成,在编译阶段将通知织入Java字节码中,也称编译时增强。AspectJ使用的是静态代理。
缺点:代理对象需要与目标对象实现一样的接口,并且实现接口的方法,会有冗余代码。同时,一旦接口增加方法,目标对象与代理对象都要维护。
动态代理
动态代理:代理类在程序运行时创建,AOP框架不会去修改字节码,而是在内存中临时生成一个代理对象,在运行期间对业务方法进行增强,不会生成新类。
JDK动态代理和CGLIB动态代理的区别?
Spring AOP中的动态代理主要有两种方式:JDK动态代理和CGLIB动态代理。
JDK动态代理
如果目标类实现了接口,Spring AOP会选择使用JDK动态代理目标类。代理类根据目标类实现的接口动态生成,不需要自己编写,生成的动态代理类和目标类都实现相同的接口。JDK动态代理的核心是InvocationHandler
接口和Proxy
类。
缺点:目标类必须有实现的接口。如果某个类没有实现接口,那么这个类就不能用JDK动态代理。
CGLIB来动态代理
通过继承实现。如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library)可以在运行时动态生成类的字节码,动态创建目标类的子类对象,在子类对象中增强目标类。
CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final
,那么它是无法使用CGLIB做动态代理的。
优点:目标类不需要实现特定的接口,更加灵活。
什么时候采用哪种动态代理?
- 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
- 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
- 如果目标对象