目录:
  • 1. 什么是spring?为什么要使用spring?
  • 2. Spring 核心包括哪几个方面?
  • 3. 什么是AOP?
  • 4. 如何实现AOP?
  • 5. AOP相关概念有哪些?
  • 6. AspectJ 注解有哪些并说明?
  • 7. Spring AOP 和 AspectJ AOP 有什么区别?
  • 8. Spring 中的 AOP 的底层实现原理是什么?
  • 9. 使用拦截器的优点是什么?
  • 10. Spring 通知类型有哪些?
  • 11. 什么是IoC?
  • 12. 为什么使用IoC?
  • 13. 什么是DI?
  • 14. IoC 和 DI 的关系是?
  • 15. spring有哪些主要模块?
  • 16. 依赖注入的常见实现方式有哪些?
  • 17. spring中的bean是线程安全的吗?
  • 18. spring支持几种bean的作用域?
  • 19. 使用单例模式的好处是什么?
  • 20. spring自动装配bean有哪些方式?
  • 21. 什么是 spring 的内部 bean?
  • 22. @Component 和 @Bean 有什么区别?
  • 23. 你知道 spring 中 Bean 的生命周期吗?
  • 24. BeanFactory 和 ApplicationContext对比?
  • 25. spring 的 JdbcTemplate 对象和 JDBC 有什么区别?
  • 26. spring事务实现方式有哪些?
  • 27. 编程性事务和声明式事务的优缺点?
  • 28. spring 事务隔离级别有哪些?
  • 29. spring 声明式事务无效可能的原因有哪些?
  • 30. spring 中都用了哪些设计模式?

1. 什么是spring?为什么要使用spring?
  • spring 是一个开源的轻量级 JavaBean 容器框架。使用 JavaBean 代替 EJB ,并提供了丰富的企业应用功能,降低应用开发的复杂性。
  • 1、轻量:非入侵性的、所依赖的东西少、资源占用少、部署简单,不同功能选择不同的 jar 组合;
  • 2、容器:工厂模式实现对 JavaBean 进行管理,通过控制反转(IOC)将应用程序的配置和依赖性与应用代码分开;
  • 3、松耦合:通过 xml 配置或注解即可完成 bean 的依赖注入;
  • 4、AOP:通过 xml 配置 或注解即可加入面向切面编程的能力,完成切面功能,如:日志,事务…的统一处理;
  • 5、方便集成:通过配置和简单的对象注入即可集成其他框架,如 Mybatis、Hibernate、Shiro;
  • 6、丰富的功能:JDBC 层抽象、事务管理、MVC、Java Mail、任务调度、JMX、JMS、JNDI、EJB、动态语言、远程访问、Web Service;
  • 点击回到目录

2. Spring 核心包括哪几个方面?
  • 1.控制反转(Ioc)
    2.依赖注入(DI)
    3.面向切面编程(AOP)

3. 什么是AOP?
  • AOP:Aspect Oriented Programming,面向切面编程。通过预编译和运行期动态代理实现程序功能的统一维护。在 Spring 框架中,AOP 是一个很重要的功能。
  • AOP 利用一种称为横切的技术,剖开对象的封装,并将影响多个类的公共行为封装到一个可重用模块,组成一个切面,即 Aspect 。"切面"就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,利于可操作性和可维护性。

4. 如何实现AOP?
  • 实现 AOP 的方式,主要有两大类:
    1、采用动态代理技术,利用拦截方法的方式,对该方法进行装饰,以取代原有对象行为的执行;
    2、采用静态织入的方式,引入特定的语法创建"切面",从而使得编译器可以在编译期间织入有关"切面"的代码。
    注:spring 框架中可以通过 xml 配置和注解去使用 AOP 功能。

5. AOP相关概念有哪些?
  • 1、Join point:连接点,程序执行期间的某一个点,例如执行方法或处理异常时候的点,在 Spring AOP 中,连接点总是表示方法的执行。
  • 2、Advice:通知,通知分为方法执行前通知,方法执行后通知、环绕通知等。许多 AOP 框架(包括 Spring)都将通知建模为拦截器,在连接点周围维护一系列拦截器(形成拦截器链),对连接点的方法进行增强。
  • 3、Pointcut:切点,匹配连接点(Join point)的表达式,是 AOP 的核心,并且 Spring 默认使用 AspectJ 作为切入点表达式语言。
  • 4、Aspect:切面,是一个跨越多个类的模块化的关注点,它是通知(Advice)和切点(Pointcut)合起来的抽象,它定义了一个切点(Pointcut)用来匹配连接点(Join point),也就是需要对需要拦截的那些方法进行定义。
  • 5、Target object:目标对象,被一个或者多个切面(Aspect)通知的对象,也就是需要被 AOP 进行拦截对方法进行增强(使用通知)的对象,也称为被通知的对象。由于在 AOP 里面使用运行时代理,因而目标对象一直是被代理的对象。
  • 6、AOP proxy:AOP 代理,为了实现切面(Aspect)功能使用 AOP 框架创建一个对象,在 Spring 框架里面一个 AOP 代理指的是 JDK 自身的动态代理或 CGLIB 实现的动态代理。
  • 7、Weaving:把切面加入到对象,并创建出代理对象的过程。
  • 8、Advisor:一个 Advisor 相当于一个小型的切面,不同的是它只有一个通知(Advice),Advisor 在事务管理里面会经常遇到。

6. AspectJ 注解有哪些并说明?
  • 1、@Before — 前置通知,在连接点方法前调用;
    2、@Around — 环绕通知,它将覆盖原有方法,但是允许你通过反射调用原有方法;
    3、@After — 后置通知,在连接点方法后调用;
    4、@AfterReturning — 返回通知,在连接点方法执行并正常返回后调用,要求连接点方法在执行过程中没有发生异常;
    5、@AfterThrowing — 异常通知,当连接点方法异常时调用。

7. Spring AOP 和 AspectJ AOP 有什么区别?
  • Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。
  • Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于
    Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单,如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比Spring AOP 快很多。

8. Spring 中的 AOP 的底层实现原理是什么?
  • Spring AOP的底层都是通过代理来实现的:
    1、一种是基于JDK的动态代理;
    2、一种是基于CgLIB的动态代理;

9. 使用拦截器的优点是什么?
  • 拦截器是基于Java反射机制实现的,使用代理模式;
    1、拦截器不依赖于servlet容器;
    2、拦截器只能对action请求起作用;
    3、拦截器可以访问action上下文;
    4、拦截器可以获取IoC容器中的各个bean;
    5、在action生命周期中,拦截器可以被多次调用;

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

11. 什么是IoC?
  • IoC,Inversion of Control(控制反转),是一种设计思想,在Java开发中,将你设计好的对象交给容器控制,而不是显示地用代码进行对象的创建。 把创建和查找依赖对象的控制权交给 IoC 容器,由 IoC 容器进行注入、组合对象。这样对象与对象之间是松耦合、便于测试、功能可复用(减少对象的创建和内存消耗),使得程序的整个体系结构可维护性、灵活性、扩展性变高。
  • 形象的说:你去某地旅游不再用自己亲自为订购 A 酒店还是 B 酒店而发愁了,只需要把住店的需求告诉给某个托管平台,这个托管平台就会帮你订购一个既便宜又舒适的酒店,而这个帮你订购酒店的行为就可以称之为控制反转。

12. 为什么使用IoC?
  • 使用IoC有以下好处:
    1、资源集中管理,实现资源的可配置和易管理;
    2、降低了资源的依赖程度,即松耦合;
    3、便于测试;
    4、功能可复用(减少对象的创建和内存消耗);
    5、使得程序的整个体系结构可维护性、灵活性、扩展性变高;

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

14. IoC 和 DI 的关系是?
  • DI 是实现 IoC 的方法和手段;

15. spring有哪些主要模块?
  • 1、Spring Core
    框架的最基础部分,提供 IoC 容器,对 bean 进行管理。
    2、Spring Context
    基于 bean,提供上下文信息,扩展出JNDI、EJB、电子邮件、国际化、校验和调度等功能。
    3、Spring DAO
    提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码,还提供了声明性事务管理方法。
    4、Spring ORM
    提供了常用的“对象/关系”映射APIs的集成层。 其中包括JPA、JDO、Hibernate、MyBatis 等。
    5、Spring AOP
    提供了符合AOP Alliance规范的面向方面的编程实现。
    6、Spring Web
    提供了基础的 Web 开发的上下文信息,可与其他 web 进行集成。
    7、Spring Web MVC
    提供了 Web 应用的 Model-View-Controller 全功能实现。

16. 依赖注入的常见实现方式有哪些?
  • 1、setter 注入(注入方式又分为java代码注入和XML配置注入);
    2、构造方法注入;
    3、注解注入;
    4、静态工厂注入;
    5、实例工厂注入;

17. spring中的bean是线程安全的吗?
  • Spring 不保证 bean 的线程安全。默认 spring 容器中的 bean 是单例的。当单例中存在竞态条件,即有线程安全问题。

18. spring支持几种bean的作用域?
  • 1、singleton:单例模式,在整个Spring IoC容器中,使用 singleton 定义的 bean 只有一个实例;
  • 2、prototype:原型模式,每次通过容器的getbean方法获取 prototype 定义的 bean 时,都产生一个新的 bean 实例;
  • 只有在 Web 应用中使用Spring时,request、session、global-session 作用域才有效;
  • 3、request:对于每次 HTTP 请求,使用 request 定义的 bean 都将产生一个新实例,即每次 HTTP 请求将会产生不同的 bean 实例;
  • 4、session:同一个 Session 共享一个 bean 实例;
  • 5、global-session:同 session 作用域不同的是,所有的Session共享一个Bean实例;

19. 使用单例模式的好处是什么?
  • 对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级对象而言,是非常可观的一笔系统开销;由于 new 操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻 GC 压力,缩短 GC 停顿时间。

20. spring自动装配bean有哪些方式?
  • spring 配置文件中 节点的 autowire 参数可以控制 bean 自动装配的方式;
    1、default - 默认的方式和 “no” 方式一样;
    2、no - 不自动装配,需要使用 < ref />节点或参数;
    3、byName - 根据名称进行装配;
    4、byType - 根据类型进行装配;
    5、constructor - 根据构造函数进行装配;

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

22. @Component 和 @Bean 有什么区别?
  • 它们的作用对象不同:@Component 作用于类,而 @Bean 注解作用于方法。
  • @Component 通常是通过类路径扫描来自动侦测和装配对象到 Spring 容器中,比如 @ComponentScan 注解就是定义扫描路径中的类装配到 Spring 的 Bean 容器中;@Bean 注解是告诉 Spring 这是某个类的实例,当我需要用它的时把它给我,@Bean 注解比 @Component 注解自定义性更强,很多地方我们只能通过 @Bean 注解来注册 Bean,比如当我们引用第三方库中的类需要装配到 Spring容器时,则只能通过 @Bean 来实现。

23. 你知道 spring 中 Bean 的生命周期吗?
  • Spring 中 Bean 的生命周期如下:
    ① 实例化 Bean:对于 BeanFactory 容器,当客户向容器请求一个尚未初始化的 Bean 时,或初始化 Bean 的时候需要注入另一个尚未初始化的依赖时,容器就会调用 createBean 进行实例化。对于 ApplicationContext 容器,当容器启动结束后,通过获取 BeanDefinition 对象中的信息,实例化所有的 Bean;
    ② 设置对象属性(依赖注入):实例化后的对象被封装在 BeanWrapper 对象中,紧接着 Spring 根据 BeanDefinition 中的信息以及通过 BeanWrapper 提供的设置属性的接口完成依赖注入;
    ③ 处理 Aware 接口:Spring 会检测该对象是否实现了 xxxAware 接口,并将相关的 xxxAware 实例注入给 Bean:
    如果这个 Bean 已经实现了 BeanNameAware 接口,会调用它实现的 setBeanName(String BeanId) 方法,此处传递的就是 Spring 配置文件中 Bean 的 id 值;
    如果这个 Bean 已经实现了 BeanFactoryAware 接口,会调用它实现的 setBeanFactory() 方法,传递的是 Spring 工厂自身;
    如果这个 Bean 已经实现了 ApplicationContextAware 接口,会调用 setApplicationContext(ApplicationContext) 方法,传入 Spring 上下文;
    ④ BeanPostProcessor:如果想对 Bean 进行一些自定义的处理,那么可以让 Bean 实现了 BeanPostProcessor 接口,那将会调用 postProcessBeforeInitialization(Object obj, String s) 方法;
    ⑤ InitializingBean 与 init-method:如果 Bean 在 Spring 配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法;
    ⑥ 如果这个 Bean 实现了 BeanPostProcessor 接口,将会调用 postProcessAfterInitialization(Object obj, String s) 方法;由于这个方法是在 Bean 初始化结束时调用的,因而可以被应用于内存或缓存技术;
    以上几个步骤完成后,Bean 就已经被正确创建了,之后就可以使用这个 Bean 了。
    ⑦ DisposableBean:当 Bean 不再需要时,会经过清理阶段,如果 Bean 实现了 DisposableBean 这个接口,会调用其实现的 destroy() 方法;
    ⑧ destroy-method:最后,如果这个 Bean 的 Spring 配置中配置了 destroy-method 属性,会自动调用其配置的销毁方法。

24. BeanFactory 和 ApplicationContext对比?
  • Spring使用工厂模式可以通过 BeanFactory 或 ApplicationContext 创建 bean 对象;
  • BeanFactory :延迟注入(使用到某个 bean 的时候才会注入),相比于BeanFactory 来说会占用更少的内存,程序启动速度更快。
  • ApplicationContext :容器启动的时候,不管你用没用到,一次性创建所有 bean 。BeanFactory 仅提供了最基本的依赖注入支持,ApplicationContext 扩展了 BeanFactory ,除了有BeanFactory的功能还有额外更多功能,所以一般开发人员使用ApplicationContext会更多。

25. spring 的 JdbcTemplate 对象和 JDBC 有什么区别?
  • Spring 的 JdbcTemplate 是对 JDBC API 的封装,提供更多的功能和更便利的操作,比如 JdbcTemplate 拥有:
    1、JdbcTemplate 是线程安全的;
    2、实例化操作比较简单,仅需要传递 DataSource;
    3、自动完成资源的创建和释放工作;
    4、创建一次 JdbcTemplate,到处可用,避免重复开发。

26. spring事务实现方式有哪些?
  • 编程式事务管理:
    在代码中调用 commit()、rollback()等事务管理相关的方法;
  • 声明式事务管理:
    1、基于 TransactionProxyFactoryBean 的声明式事务管理;
    2、基于注解 @Transactional 的声明式事务管理;
    3、基于 Aspectj AOP 配置(注解)事务;

27. 编程性事务和声明式事务的优缺点?
  • 编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。
  • 声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
  • 声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。
  • 显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。和编程式事务相比,声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。
  • 声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。

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

29. spring 声明式事务无效可能的原因有哪些?
  • 1、如使用mysql且引擎是MyISAM,则事务会不起作用,原因是MyISAM不支持事务,可以改成InnoDB;
  • 2、如果使用了spring+mvc,则context:component-scan重复扫描问题可能会引起事务失败;
  • 3、@Transactional 注解开启配置,必须放到listener里加载,如果放到DispatcherServlet的配置里,事务也是不起作用的;
  • 4、@Transactional 注解只能应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错,事务也会失效;
  • 5、Spring团队建议在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。在接口上使用 @Transactional 注解,只能当你设置了基于接口的代理时它才生效。因为注解是 不能继承 的,这就意味着如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装。

30. spring 中都用了哪些设计模式?
  • 工厂设计模式:Spring使用工厂模式可以通过 BeanFactory 或 ApplicationContext 创建 bean 对象;
  • 单例设计模式:在我们的系统中,有一些对象其实我们只需要一个,比如说:线程池、缓存、对话框、注册表、日志对象、充当打印机、显卡等设备驱动程序的对象。事实上,这一类对象只能有一个实例,如果制造出多个实例就可能会导致一些问题的产生,比如:程序的行为异常、资源使用过量、或者不一致性的结果。
  • 代理设计模式:AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
  • 观察者模式:观察者模式是一种对象行为型模式。它表示的是一种对象与对象之间具有依赖关系,当一个对象发生改变的时候,这个对象所依赖的对象也会做出反应。Spring 事件驱动模型就是观察者模式很经典的一个应用。Spring 事件驱动模型非常有用,在很多场景都可以解耦我们的代码。比如我们每次添加商品的时候都需要重新更新商品索引,这个时候就可以利用观察者模式来解决这个问题。
  • 适配器模式:适配器模式(Adapter Pattern) 将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。
  • 装饰者模式:装饰者模式可以动态地给对象添加一些额外的属性或行为。