目录 1. Spring基础1.1 什么是 spring?Spring是一个轻量级Java开发框架,最早有Rod Johnson创建,目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。它是一个分层的JavaSE/JavaEE full-stack(一站式)轻量级开源框架,为开发Java应用程序提供全面的基础架构支持。Spring负责基础架构,因此Java开发者可以专注于应用程序的开发。 Spring最根本的使命是解决企业级应用开发的复杂性,即简化Java开发。 Spring可以做很多事情,它为企业级开发提供给了丰富的功能,但是这些功能的底层都依赖于它的两个核心特性,也就是依赖注入(dependency injection,DI)和面向切面编程(aspect-oriented programming,AOP)。 为了降低Java开发的复杂性,Spring采取了以下4种关键策略
1.2 Spring框架的设计目标,设计理念,和核心是什么?
IoC让相互协作的组件保持松散的耦合,而AOP编程允许你把遍布于应用各层的功能分离出来形成可重用的功能组件。 1.3 Spring 框架中都用到了哪些设计模式?
1.4 Spring Framework 中有多少个模块,它们分别是什么?Spring 总共大约有 20 个模块, 由 1300 多个不同的文件构成。 而这些组件被分别整合在
1.5 spring context应用上下文有什么作用?这是基本的Spring模块,提供spring 框架的基础功能,BeanFactory 是 任何以spring为基础的应用的核心。Spring 框架建立在此模块之上,它使Spring成为一个容器。 Bean 工厂是工厂模式的一个实现,提供了控制反转功能,用来把应用的配置和依赖从真正的应用代码中分离。最常用的就是org.springframework.beans.factory.xml.XmlBeanFactory ,它根据XML文件中的定义加载beans。该容器从XML 文件读取配置元数据并用它去创建一个完全配置的系统或应用。 1.6 Spring 应用程序有哪些不同组件?Spring 应用一般有以下组件:
1.7 使用 Spring 有哪些方式?
1.8 Spring的优缺点是什么?
1.9 Spring框架中有哪些不同类型的事件?Spring 提供了以下5种标准的事件:
2. Spring IoC2.1 什么是 Spring IOC 容器?控制反转即IoC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。 Spring IOC 负责创建对象,管理对象(通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期 2.2 控制反转(IoC)有什么作用?
2.3 可以通过多少种方式完成依赖注入?通常,依赖注入可以通过三种方式完成,即:
2.4 Spring 如何设计容器的,BeanFactory和ApplicationContext的关系详解?Spring 作者 Rod Johnson 设计了两个接口用以表示容器。
BeanFactory 简单粗暴,可以理解为就是个 HashMap,Key 是 BeanName,Value 是 Bean 实例。通常只提供注册(put),获取(get)这两个功能。我们可以称之为 “低级容器”。 ApplicationContext 可以称之为 “高级容器”。因为他比 BeanFactory 多了更多的功能。他继承了多个接口。因此具备了更多的功能。例如资源的获取,支持多种消息(例如 JSP tag 的支持),对 BeanFactory 多了工具级别的支持等待。所以你看他的名字,已经不是 BeanFactory 之类的工厂了,而是 “应用上下文”, 代表着整个大容器的所有功能。该接口定义了一个 refresh 方法,此方法是所有阅读 Spring 源码的人的最熟悉的方法,用于刷新整个容器,即重新加载/刷新所有的 bean。 当然,除了这两个大接口,还有其他的辅助接口,这里就不介绍他们了。 BeanFactory和ApplicationContext的关系 为了更直观的展示 “低级容器” 和 “高级容器” 的关系,这里通过常用的 ClassPathXmlApplicationContext 类来展示整个容器的层级 UML 关系。 看下面的隶属 ApplicationContext 粉红色的 “高级容器”,依赖着 “低级容器”,这里说的是依赖,不是继承哦。他依赖着 “低级容器” 的 getBean 功能。而高级容器有更多的功能:支持不同的信息源头,可以访问文件资源,支持应用事件(Observer 模式)。 通常用户看到的就是 “高级容器”。 但 BeanFactory 也非常够用啦! 左边灰色区域的是 “低级容器”, 只负载加载 Bean,获取 Bean。容器其他的高级功能是没有的。例如上图画的 refresh 刷新 Bean 工厂所有配置,生命周期事件回调等。 小结 说了这么多,不知道你有没有理解Spring IoC? 这里小结一下:IoC 在 Spring 里,只需要低级容器就可以实现,2 个步骤:
上面就是 Spring 低级容器(BeanFactory)的 IoC。 至于高级容器 ApplicationContext,他包含了低级容器的功能,当他执行 refresh 模板方法的时候,将刷新整个容器的 Bean。同时其作为高级容器,包含了太多的功能。一句话,他不仅仅是 IoC。他支持不同信息源头,支持 BeanFactory 工具类,支持层级容器,支持访问文件资源,支持事件发布通知,支持接口回调等等。 2.5 IoC 的好处有哪些?
2.6 Spring IoC 的实现机制Spring 中的IoC 的实现原理就是工厂模式加反射机制 。 interface Fruit { public abstract void eat(); } class Apple implements Fruit { public void eat(){ System.out.println("Apple"); } } class Orange implements Fruit { public void eat(){ System.out.println("Orange"); } } class Factory { public static Fruit getInstance(String ClassName) { Fruit f=null; try { f=(Fruit)Class.forName(ClassName).newInstance(); } catch (Exception e) { e.printStackTrace(); } return f; } } class Client { public static void main(String[] a) { Fruit f=Factory.getInstance("com.xxx.xxx.Apple"); if(f!=null){ f.eat(); } } } 2.7 Spring 的 IoC支持哪些功能?Spring 的 IoC 设计支持以下功能:
其中,最重要的就是依赖注入,从 XML 的配置上说,即 ref 标签。对应 Spring RuntimeBeanReference 对象。 对于 IoC 来说,最重要的就是容器。容器管理着 Bean 的生命周期,控制着 Bean 的依赖注入。 2.8 BeanFactory 和 ApplicationContext有什么区别?BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。
2.9 ApplicationContext通常的实现是什么?
2.10 什么是Spring的依赖注入?控制反转IoC是一个很大的概念,可以用不同的方式来实现。其主要实现方式有两种:依赖注入和依赖查找 依赖注入:相对于IoC而言,依赖注入(DI)更加准确地描述了IoC的设计理念。所谓依赖注入(Dependency Injection),即组件之间的依赖关系由容器在应用系统运行期来决定,也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。 2.11 依赖注入的基本原则是什么?依赖注入的基本原则是:应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由IoC容器负责,“查找资源”的逻辑应该从应用组件的代码中抽取出来,交给IoC容器负责。容器全权负责组件的装配,它会把符合依赖关系的对象通过属性(JavaBean中的setter)或者是构造器传递给需要的对象。 2.12 依赖注入有什么优势?依赖注入之所以更流行是因为它是一种更可取的方式:让容器全权负责依赖查询,受管组件只需要暴露JavaBean的setter方法或者带参数的构造器或者接口,使容器可以在初始化时组装对象的依赖关系。其与依赖查找方式相比,主要优势为:
2.13 构造器依赖注入和 Setter方法注入有什么区别?
两种依赖方式都可以使用,构造器注入和Setter方法注入。最好的解决方案是用构造器参数实现强制依赖,setter方法实现可选依赖。 3. Spring Beans3.1 什么是 spring bean?
3.2 spring 提供了哪些配置方式?
3.3 spring 支持几种 bean scope?Spring bean 支持5种scope:
3.4 spring bean 容器的生命周期是什么样的?spring bean 容器的生命周期流程如下: 1、Spring 容器根据配置中的 bean 定义中实例化 bean。 3.5 什么是 spring 的内部 bean?只有将 bean 用作另一个 bean 的属性时,才能将 bean 声明为内部 bean。为了定义 bean, Spring 的基于 XML 的配置元数据在或 中提供了元素的使用 。 内部 bean 总是匿名的,它们总是作为原型。 例如,假设我们有一个 Student 类,其中引用了 Person 类。 这里我们将只创建一个 Person 类实例并在 Student 中使用它。 Student.java public class Student { private Person person; //Setters and Getters } Person.java public class Person { private String name; private String address; //Setters and Getters } bean.xml <bean id=“StudentBean" class="com.lupf.Student"> <property name="person"> <!--This is inner bean --> <bean class="com.lupf.Person"> <property name="name" value=“Scott"></property> <property name="address" value="Bangalore"></property> </bean> </property> </bean> 3.6 什么是bean装配?什么是bean的自动装配?装配,或bean装配是指在Spring容器中把bean组装到一起,前提是容器需要知道bean的依赖关系,如何通过依赖注入来把它们装配到一起。 在Spring框架中,在配置文件中设定bean的依赖关系是一个很好的机制,Spring 容器能够自动装配相互合作的bean,这意味着容器不需要和配置,能通过Bean工厂自动处理bean之间的协作。这意味着 Spring可以通过向Bean Factory中注入的方式自动搞定bean之间的依赖关系。自动装配可以设置在每个bean上,也可以设定在特定的bean上。 3.7 自动装配有哪些方式?Spring容器能够自动装配bean。也就是说,可以通过检查BeanFactory的内容让Spring自动解析bean的协作者。 自动装配的不同模式:
3.8 自动装配有什么局限?
3.9 使用@Autowired注解自动装配的过程是怎样的?使用@Autowired注解来自动装配指定的bean。在使用@Autowired注解之前需要在Spring配置文件进行配置,<context:annotation-config />。 在启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性。在使用@Autowired时,首先在容器中查询对应类型的bean:
3.10 Spring配置文件包含了哪些信息?Spring配置文件是个XML 文件,这个文件包含了类信息,描述了如何配置它们,以及如何相互调用。 3.11 Spring基于xml注入bean的几种方式
3.12 Spring框架中的单例bean是线程安全的吗?不是,Spring框架中的单例bean不是线程安全的。 spring 中的 bean 默认是单例模式,spring 框架并没有对单例 bean 进行多线程的封装处理。 实际上大部分时候 spring bean 无状态的(比如 dao 类),所有某种程度上来说 bean 也是安全的,但如果 bean 有状态的话(比如 view model 对象),那就要开发者自己去保证线程安全了,最简单的就是改变 bean 的作用域,把“singleton”变更为“prototype”,这样请求 bean 相当于 new Bean()了,所以就可以保证线程安全了。
3.13 Spring如何处理线程并发问题?在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域,因为Spring对一些Bean中非线程安全状态采用ThreadLocal进行处理,解决线程安全问题。 ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。而ThreadLocal采用了“空间换时间”的方式。 ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。 3.14 bean生命周期方法有哪些? 你能重载它们吗?有两个重要的bean 生命周期方法:
bean 标签有两个重要的属性(init-method和destroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解(@PostConstruct和@PreDestroy)。 3.15 在 Spring中如何注入一个java集合?Spring提供以下几种集合的配置元素:
3.16 你可以在Spring中注入一个null 和一个空字符串吗?可以。 4. Spring注解4.1 什么是基于Java的Spring注解配置?基于Java的配置,允许你在少量的Java注解的帮助下,进行你的大部分Spring配置而非通过XML文件。 以@Configuration 注解为例,它用来标记类可以当做一个bean的定义,被Spring IOC容器使用。 另一个例子是@Bean注解,它表示此方法将要返回一个对象,作为一个bean注册进Spring应用上下文。 @Configuration public class StudentConfig { @Bean public StudentBean myStudent() { return new StudentBean(); } } 4.2 怎样开启注解装配?注解装配在默认情况下是不开启的,为了使用注解装配,我们必须在Spring配置文件中配置 4.3 @Component, @Controller, @Repository, @Service 有何区别?
4.4 @Required 注解有什么作用?这个注解表明bean的属性必须在配置的时候设置,通过一个bean定义的显式的属性值或通过自动装配,若@Required注解的bean属性未被设置,容器将抛出BeanInitializationException。示例: public class Employee { private String name; @Required public void setName(String name){ this.name=name; } public string getName(){ return name; } } 4.5 @Autowired 注解有什么作用?@Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。@Autowired 注解提供了更细粒度的控制,包括在何处以及如何完成自动装配。它的用法和@Required一样,修饰setter方法、构造器、属性或者具有任意名称和/或多个参数的PN方法。 public class Employee { private String name; @Autowired public void setName(String name) { this.name=name; } public string getName(){ return name; } } 4.6 @Autowired和@Resource有什么区别?@Autowired可用于:构造函数、成员变量、Setter方法 @Autowired和@Resource之间的区别
4.7 @Qualifier注解有什么作用?当您创建多个相同类型的 bean 并希望仅使用属性装配其中一个 bean 时,您可以使用@Qualifier 注解和 @Autowired 通过指定应该装配哪个确切的 bean 来消除歧义。 4.8 @RequestMapping注解有什么用?@RequestMapping 注解用于将特定 HTTP 请求方法映射到将处理相应请求的控制器中的特定类/方法。此注释可应用于两个级别:
5. Spring数据访问5.1 解释对象/关系映射集成模块Spring 通过提供ORM模块,支持我们在直接JDBC之上使用一个对象/关系映射映射(ORM)工具,Spring 支持集成主流的ORM框架,如Hiberate,JDO和 iBATIS,JPA,TopLink,JDO,OJB 。Spring的事务管理同样支持以上所有ORM框架及JDBC。 5.2 在Spring框架中如何更有效地使用JDBC?使用Spring JDBC 框架,资源管理和错误处理的代价都会被减轻。所以开发者只需写statements 和 queries从数据存取数据,JDBC也可以在Spring框架提供的模板类的帮助下更有效地被使用,这个模板叫JdbcTemplate 5.3 解释JDBC抽象和DAO模块的作用是什么?通过使用JDBC抽象和DAO模块,保证数据库代码的简洁,并能避免数据库资源错误关闭导致的问题,它在各种不同的数据库的错误信息之上,提供了一个统一的异常访问层。它还利用Spring的AOP 模块给Spring应用中的对象提供事务管理服务。 5.4 Spring DAO 有什么用?Spring DAO(数据访问对象) 使得 JDBC,Hibernate 或 JDO 这样的数据访问技术更容易以一种统一的方式工作。这使得用户容易在持久性技术之间切换。它还允许您在编写代码时,无需考虑捕获每种技术不同的异常。 5.5 Spring JDBC API 中存在哪些类?
5.6 JdbcTemplate是什么?JdbcTemplate 类提供了很多便利的方法解决诸如把数据库数据转变成基本数据类型或对象,执行写好的或可调用的数据库操作语句,提供自定义的数据错误处理。 5.7 Spring通过什么方式访问Hibernate?在Spring中有两种方式访问Hibernate:
5.8 如何通过HibernateDaoSupport将Spring和Hibernate结合起来?用Spring的 SessionFactory 调用 LocalSessionFactory。集成过程分三步:
5.9 Spring支持的事务管理类型是什么?spring 事务实现方式有哪些?Spring支持两种类型的事务管理:
5.10 Spring事务的实现方式和实现原理是什么?Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。 5.11 Spring的事务传播行为有那些?Spring事务的传播行为说的是,当多个事务同时存在的时候,spring如何处理这些事务的行为。
5.12 说一下 Spring 的事务隔离?spring 有五大隔离级别,默认值为 ISOLATION_DEFAULT(使用数据库的设置),其他四个隔离级别和数据库的隔离级别一致:
脏读 :表示一个事务能够读取另一个事务中还未提交的数据。比如,某个事务尝试插入记录 A,此时该事务还未提交,然后另一个事务尝试读取到了记录 A。 不可重复读 :是指在一个事务内,多次读同一数据。 幻读 :指同一个事务内多次查询返回的结果集不一样。比如同一个事务 A 第一次查询时候有 n 条记录,但是第二次同等条件下查询却有 n+1 条记录,这就好像产生了幻觉。发生幻读的原因也是另外一个事务新增或者删除或者修改了第一个事务结果集里面的数据,同一个记录的数据内容被修改了,所有数据行的记录就变多或者变少了。 5.13 Spring框架的事务管理有哪些优点?
5.14 你更倾向用那种事务管理类型?大多数Spring框架的用户选择声明式事务管理,因为它对应用代码的影响最小,因此更符合一个无侵入的轻量级容器的思想。声明式事务管理要优于编程式事务管理,虽然比编程式事务管理(这种方式允许你通过代码控制事务)少了一点灵活性。唯一不足地方是,最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。 6. Spring AOP6.1 什么是AOP?OOP(Object-Oriented Programming)面向对象编程,允许开发者定义纵向的关系,但并适用于定义横向的关系,导致了大量代码的重复,而不利于各个模块的重用。 AOP(Aspect-Oriented Programming),一般称为面向切面编程,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理等。 6.2 Spring AOP and AspectJ AOP 有什么区别?AOP 有哪些实现方式?AOP实现的关键在于 代理模式,AOP代理主要分为静态代理和动态代理。静态代理的代表为AspectJ;动态代理则以Spring AOP为代表。 1. AspectJ是静态代理的增强,所谓静态代理,就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强,他会在编译阶段将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。 2. Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。 6.3 JDK动态代理和CGLIB动态代理的区别是什么?Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理:
静态代理与动态代理区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。
6.4 如何理解 Spring 中的代理?将 Advice 应用于目标对象后创建的对象称为代理。在客户端对象的情况下,目标对象和代理对象是相同的。 Advice + Target Object = Proxy 6.5 请解释一下Spring AOP核心的名称分别是什么意思?
6.6 为什么Spring只支持方法级别的连接点?因为Spring基于动态代理,所以Spring只支持方法连接点。Spring缺少对字段连接点的支持,而且它不支持构造器连接点。方法之外的连接点拦截功能,我们可以利用Aspect来补充。 6.7 Spring AOP 中,关注点和横切关注的区别是什么?关注点(concern)是应用中一个模块的行为,一个关注点可能会被定义成一个我们想实现的一个功能。 横切关注点(cross-cutting concern)是一个关注点,此关注点是整个应用都会使用的功能,并影响整个应用,比如日志,安全和数据传输,几乎应用的每个模块都需要的功能。因此这些都属于横切关注点。 6.8 Spring通知有哪些类型?在AOP术语中,切面的工作被称为通知,实际上是程序执行时要通过SpringAOP框架触发的代码段。 Spring切面可以应用5种类型的通知:
同一个aspect,不同advice的执行顺序:
6.9 什么是切面 Aspect?aspect 由 pointcount 和 advice 组成,切面是通知和切点的结合。 它既包含了横切逻辑的定义, 也包括了连接点的定义. Spring AOP 就是负责实施切面的框架, 它将切面所定义的横切逻辑编织到切面所指定的连接点中.
可以简单地认为, 使用 @Aspect 注解的类就是切面. 6.10 什么是基于XML Schema方式的切面实现?在这种情况下,切面由常规类以及基于XML的配置实现。 6.11 什么是基于注解的切面实现?在这种情况下(基于@AspectJ的实现),涉及到的切面声明的风格与带有java5标注的普通java类一致。 6.12 有几种不同类型的自动代理?
|
|