目录
@Component、@Controller、@Repository、@Service有何区别?
Sprng支持的事务管理类型,spring事务实现方式有哪些?
大家一起加油吧 ! ! !
什么是Spring?
1. Spring是一个轻量级Java开发框架。
2. Spring最根本的使命是解决企业级应用开发的复杂性,即简化Java开发。
3. Spring可以做很多事情,它为企业级开发提供给了丰富的功能,但是这些功能的底层都是依赖于它的两个核心特性,也就是依赖注入(dependecy)
为降低Java开发的复杂性,Spring采取了以下4种关键策略
1. 基于POJO的轻量级和最小侵入性编程;
2. 通过依赖注入和面向接口实现松耦合;
3. 基于切面和惯例进行声明式编程;
4. 通过切面和模板减少样板式代码;
Spring的两大核心概念
1. IOC(控制反转):
控制翻转,也叫依赖注入,他就是不会直接创建对象,只是把对象声明出来再代码中不直接于对象和服务器进行连接,但是再配置文件中描述了哪一项服务,容器将它们组件起来。再一般IOC场景容器创建了所有的对象,并设置了必要的属性将它们联系在一起,等到需要使用的时候才把它们声明出来,使用注解就更方便,容器会自动根据注解把对象组合起来
2. AOP(面向切面编程):
面对切面编程,这是一种编程模式,他允许程序员通过自定义的横切点进行模块化,将哪些影响多个类的行为封装到可重用的模块种。例如:比如日志输出语句封装一个可重用模块,在以声明的方式将他们放在类中,每次实用类就自动完成了日志输出。
Spring框架的设计目标,设计理念,和核心是什么
Spring设计目标:Spring为开发者提供一个一站式轻量级应用开发平台;
Spring设计理念:在JavaEE开发中,支持POJO和JavaBean开发方式,使用面向接口开发,充分支持OOP(面向对象)设计方法; Spring通过ioc容器实现对象耦合关系的惯例,并实现依赖反转,将对象之间的依赖关系交给IOC容器,实现解耦
Spring框架的核心:IOC容器和AOP模块。通过IOC容器管理POJO对象以及他们之间按耦合关系;通过AOP以动态非侵入的方式增强服务。
IOC让相互协作的组件保存松散的耦合,而AOP编程允许你把遍布于应用各层的功能分离出来可以形成可重用的功能组件
Spring的优缺点是什么?
优点
- 方便解耦,简化开发
Spring就一个大工厂,可以将所有对象的创建和依赖关系的维护,交给Spring管理。 - AOP编程的支持
Spring提供面向切面编程,可以方便的实现对程序进行权限拦截,运行监控等功能。 - 声明式事务的支持
只需要通过配置就可以完成对事务的管理,而无序手动编程。 - 方便程序的测试
Spring对Junit4支持,可以通过注解方便的测试Spring程序。 - 方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,其内部提供了各种优秀框架的直接支持(如:Struts,Hibernate,MyBatis等) - 降低JavaEE API的使用难度
Spring对JavaEE开发种非常难用的一些API(JDBC,JavaMail,远程调用等),都提供了封装,使用这些API应用难度大大降低
缺点
- Spring明明一个很轻量级的框架,却给人感觉大而全
- Spring依赖反射,反射影响性能
- 使用门槛升高,入门Spring需要较长时间
Spring由哪些应用场景
- 应用场景:JavaEE企业应用开发,包括SSH,SSM等
Spring价值:
- Spring是非侵入式的框架,目标是使应用程序代码对框架依赖最小化;
- Spring提供一个一致的编程模型,使应用直接使用POJO开发,与运行环境隔离开来;
- Spring推动应用设计风格面向对象的面向接口开发转变,提高了代码的重用性和可测试性;
Spring由哪些模块组成?
- Spring总共大约由20个模块,由1300多个不同的文件构成。而这些组件分别整合在核心容器(Core Cotainer)、AOP(Aspect Oriented Programming)和设备支持(Instrmentaion)、数据访问与集成(Data Access/Integeration)、Web、消息(Messaging)、Test等6个模块中。以下是Spring5的模块结构
- Spring core:提供了框架的基本组成部分,包括控制反转(Inversion of Control ,IOC)和依赖注入(Dependency Injection ,DI)功能。
- Spring beans:提供了BeanFactory,是工厂模式的一个经典实现,Spring将管理对象称为Bean。
- Spring contest:构建与core封装与core封装包基础上的context封装包,提供了一种框架式的对象访问方法。
- Spring jdbc:提供了面向切面的编程实现,让你可以自定义拦截器,切点等。
- Spring Web:提供了针对Web开发的集成特性,例如文件上传,利用servlet listeners经行ioc容器初始化和针对Web的ApplicationContext。
- Spring test:主要为测试提供支持的,支持使用Junit或TestNG对Spring组件进行单元测试和集成测试。
Spring框架中都用到了那些设计模式?
1. 工厂模式:BeanFactory就是一个简单工厂模式
2. 单例模式:Bean默认为单例模式。
3. 代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码涩生成技术。
4. 模板方法:用来解决代码重复问题。比如,RestTemplate,JmsTemplate,JpaTemplate。
5. 观察者模式: 定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所依赖它的对象就会得到通知被动更新,如Spring中listener的实现-ApplicationListener
Spring应用程序有哪些不同组件?
1. 接口:定义功能。
2. Bean类:它包含属性,setter和getter方法,函数等。
3. Bean配置文件:包含类的信息以及如何优化配置
4. Spring面向切面编程(AOP):提供面向切面编程的功能。
5. 用户程序:它使用接口。
Spring控制反转(IOC)
什么是Spring IOC容器?
1. 控制反转即IOC(Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器的转移,从程序代码本省转移到外部容器。
2. Spring IOC负责创建对象,管理对象(通过依赖注入DI),装配对象,配置对象,并且管理这些对象的整个生命周期
控制反转(IOC)有什么作用
1. 管理对象的创建和依赖关系的维护。对象的创建并不是一件简单的事,在对象关系比较复杂时,如果依赖关系需要程序员来维护的话,那是相当头痛的。
2. 解耦,由容器去维护具体的对象
3. 托管了类的产生过程,比如我们需要产生过程中做一些处理,最直接的例子就是代理,如果由容器程序可以把这部分处理交给容器,应用程序则无需去关心类是如何完成代理的
IOC的优点是什么?
1. IOC或依赖注入把应用的代码量降到最低。
2. 它使应用容器测试,单元测试不再需要单例和NDI查找机制。
3. 最小的代缴和最小的侵入性使松耦合得以实现。
4. IOC容器支持加载服务时的饿汉式初始化和懒加载。
什么是Spring的依赖注入
控制反转IOC是一个很大的概念,可以用不同的方式来实现。其主要实现方式有两种:依赖注入和依赖查找依赖注入:相对于IOC而言,依赖注入(DI)更加准确描述了IOC的设计理念。所谓依赖注入(Dependecy Injection),即组件之间的依赖关系有容器在应用系统运行期间来决定,也就是由容器动态地将某种依赖关系地目标对象实例注入到应用系统中地各个关联地组件之中。组件不做定位查询,只提供普通地Java方法让容器去决定依赖关系。
依赖注入的基本原则
依赖注入的基本原则是:应用组件不应该负责查找资源或者其他依赖协作对象。配置对象的工作应该由IOC容器负责,“查找资源”的逻辑应该从应用组件的代码中抽取出来,交给IOC容器负责。容器全权负责组件的装配,他会把符合依赖关系的对象通过属性(JavaBean中setter)或则是构造器传递给需要的对象
依赖注入有什么优势
依赖注入之所以更流行时是因为它时一种更可取的方式:让容器全权负责依赖查询,受管组件只需要暴露JavaBean的setter方法或者带参数的构造器或者接口,使容器可以在初始化时组装对象的依赖关系。其与依赖查找方式相比,主要优势为:
- 查找定位操作与应用代码完全无关。
- 不依赖于容器的API,可以很容器地在任何容器以外使用应用对象。
- 不需要特殊的接口,绝大多数对象可以做到完全不必依赖容器。
有哪些不同类型地依赖注入实现方式?
- 依赖注入是时下最流行地IOC实现方式,依赖注入分为接口注入(Interface Injection),Setter方法注入(Setter Injection)和构造器注入(Constructor Injection)三种方式。其中接口注入由于在灵活性和易用性比较差,现在从Spring4开始已被废弃。
- 构造依赖注入:构造器依赖注入通过容器触发一个类地构造器来实现地,该类有一系列参数,每个参数代表一个对他类的依赖。
- Setter方法注入:Setter方法注入是容器通过调用无参构造器或无参static工厂方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。
构造依赖注入和Setter方法注入的区别
构造函数注入 | setter注入 |
没有部分注入 | 有部分注入 |
不会覆盖setter属性 | 会覆盖setter属性 |
任意修改都会创建一个新实例 | 任意修改不会创建一个新实例 |
适用于设置很多属性 | 适用于设置少量属性 |
Spring面向切面编程(AOP)
什么是AOP
- OOP,面向对象编程,允许开发者定义纵向的关系,允许开发者定义纵向的关系,并适用于定义横向的关系,导致大量代码的重复,而不利于各个模块的重用。
- AOP,一般被称为面向切面编程,作为面向切面编程,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名未“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证,日志,事务处理等。
JDK动态代理和CGLIB动态代理的区别
- Spring AOP中动态代理主要两种方式,JDK动态代理和CGLIB动态代理:
-
- JDK动态代理只是提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类,InvocationHandler通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编制在一起;接着,Proxy利用InvocaionHandler动态创建一个符合某一接口地实例,生成目标类代理对象。
- 如果代理类没有实现InvocationHandler接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成地类库,可以在运行是动态地生成指定类地一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某哥类被标记为final,那么它是无法使用CGLIB做动态代理的。
- 静态代理与动态代理区别在于生成AOP代理对象的时机不同,相对来说Aspect的静态代理方式具有更好的性能,但是Aspect需要特定编译器进行处理,而Spring AOP则不需特定的编译器处理
解释以下Spring AOP里面的几个名词
切面(Aspect):切面是通知和切点的结合。通知和切点共同定义了切面的全部内容。在Spring AOP中,切面可以使用通用类(基于模式的风格)或者在不同类中一@AspectJ注解来实现
连接点(Join Point):指方法,在Spring AOP中,一个连接点总是代表一个方法的执行。应用可能有数以前几的时机应用通知。这些被称为连接点。连接点是在应用执行过程中能够插入切面的一个点。这个点可以调用方法时,抛出异常时,甚至修改一个字段时。切脉你代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。
通知(Advice):在AOP术语中,切面的工作会被称为通知;
切入点(Pointcut):切点的定义会匹配通知所要织入的一个或多个连接点。我们通常使用
明确的类和方法名称,或是利用正则表达式定义所匹配的类和方法名称来指定这些切点。
引入(Introduction):引入允许我们向现有类添加新方法或属性。
目标对象(Target Object): 被一个或者多个切面(aspect)所通知(advise)的对象。
它通常是一个代理对象。也有人把它叫做 被通知(adviced) 对象。 既然Spring AOP是通过运行
时代理实现的,这个对象永远是一个 被代理(proxied) 对象。
织入(Weaving):织入是把切面应用到目标对象并创建新的代理对象的过程。在目标对象
的生命周期里有多少个点可以进行织入:
- 编译期:切面在目标类编译时被织入。AspectJ的织入编译器是以这种方式织入切面的。
- 类加载期:切面在目标类加载到JVM时被织入。需要特殊的类加载器,它可以在目标类被引入应用之前增强该目标类的字节码。AspectJ5的加载时织入就支持以这种方式织入切面
- 运行期:切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态地创建一个代理对象。SpringAOP就是以这种方式织入切面。
Spring Beans
什么是Spring beans?
Spring Beans是那些形成Spring应用的主干的java对象。它们被Spring IOC容器初始化,装配,和管理。这些beans通过容器中配置的元数据创建。比如,以XML文件中的形式定义。
Spring Bean定义包含什么?
一个spring bean 的定义包含容器必知的所有配置元数据,包括如何创建一个bean,它的生命周期详情及它的依赖。
Spring如何处理线程并发问题?
- 在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为sigleton作用域,因为Spring对一些Bean中非线程安全状态采用ThreadLocal进行处理,解决线程安全问题。
- ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。而ThreadLocal采用了“空间换时间”的方式。
- ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。
解释Spring框架中Bean的生命周期
在传统的Java应用中,bean的生命周期很简单。使用Java关键字new进行bean实例化,然后该bean就可以使用了。一旦该bean不再被使用,则由Java自动回收进行垃圾回收。相比之下,Spring容器中的bean的生命周期就显得相对复杂多了。正确理解springbean的生命周期非常重要,因为你或许要利用Spring提供的扩展点来定义bean的创建过程。下图展示bean装载到spring应用上下文中的一个典型的生命周期过程。
bean在spring容器中创建到销毁尽力了若干阶段,每一阶段都可以针对spring如何管理bean进行个性化定制。
正如你所见,在bean尊卑就绪之前,bean工厂执行了若干启动步骤。
我们对上图进行详细描述:
- Spring对bean进行实例化;
- Spring将值和bean的引用注入到bean对应得属性中;
- 如果bean实现了BeanNameAware接口,Spring将bean得ID传递给setBean-Name()方法;
- 如果bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入;
- 如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在应用上下文得引用传入进来;
- 如果bean实现了BeanPostProcessor接口,Spring将调用它们得post-ProcessVeforInitialization()方法;
- 如果bean实现了Init-ilalizingBean接口,Spring将调用它们得after-PropertiesSet()方法。类似地,如果bean实现init-method生命了初始化方法,该方法也会被调用;
- 如果bean实现了BeanPostProcessor接口,Spring将调用它们的post-ProcessAfterInitialication()方法;
- 此时,bean已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁;
- 如果bean实现了DisposableBean接口,Spring将调用它的destroy()接口方法同样,如果bean使用destroy-method声明了销毁方法,该方法也会被调用。
现在你已经了解了如何创建和加载一个Spring容器。但是一个空的容器并没有太大的价值,在你把东西放进去之前,它里面什么都没有。为了从spring的DI(依赖注入)中受益,我们必须将应用对象装配进spring容器中;
SpringBean
-
Bean的实例化:
-
- Spring通过BeanDefinition中的信息调用无参构造器或带有特定注解(如
@Autowired
)的构造器来创建Bean实例。 - 如果没有合适的构造器,Spring会选择无参构造器创建实例。
- Spring通过BeanDefinition中的信息调用无参构造器或带有特定注解(如
-
Bean属性填充:
-
- 在实例化之后,Spring会根据BeanDefinition中配置的信息填充Bean的属性。
- 属性可以通过XML中的
<property>
标签或者Java配置类中的@Autowired
等方式定义。
-
Bean初始化:
-
- Aware接口:如果Bean实现了某些Spring的Aware接口(例如
BeanFactoryAware
,ApplicationContextAware
),Spring会在适当的时候调用相应的set方法。 - BeanPostProcessor:在初始化前后,Spring会调用BeanPostProcessor的
postProcessBeforeInitialization
和postProcessAfterInitialization
方法。 @PostConstruct
注解:如果有方法标记了@PostConstruct
注解,那么Spring会在初始化过程中调用该方法。- InitializingBean接口:如果Bean实现了
InitializingBean
接口,那么Spring会调用其afterPropertiesSet()
方法。 - 自定义初始化方法:可以在XML中通过
init-method
属性指定一个初始化方法;在Java配置中则可以通过@Bean
注解的initMethod
属性来指定。
- Aware接口:如果Bean实现了某些Spring的Aware接口(例如
-
Bean进入服务状态:
-
- 初始化完成后,Bean进入可用状态,可以被其他Bean使用。
-
Bean销毁:
-
- 当Spring容器关闭时,Bean会被销毁。
- DisposableBean接口:如果Bean实现了
DisposableBean
接口,那么Spring会在销毁时调用其destroy()
方法。 @PreDestroy
注解:如果有方法标记了@PreDestroy
注解,那么Spring会在销毁时调用该方法。- 自定义销毁方法:可以在XML中通过
destroy-method
属性指定一个销毁方法;在Java配置中则可以通过@Bean
注解的destroyMethod
属性来指定。
Spirng注解
什么是基于Java的spring注解配置?给一些注解的例子
- 基于Java的配置,允许你在少量的Java注解的帮助下,进行你的大部分spring配置而非通过xml文件。
- 以@Configuration注解为例,它用来标记类可以当做一个bean的定义,被Spring IOC容器使用。
- 另一个例子是@Bean注解,它表示此方法要返回一个对象,作为一个bean注解进spring应用上下文。
@Configuration
public class StudentConfig {
@Bean
public StudentBean myStudent() {
return new StudentBean();
}
}
怎么样开启注解装配?
- 注解装配在默认情况下是不开启的,为了使用注解装配,我们必须在spring配置文件中配置<context:annotation-cofnig/>元素。
@Component、@Controller、@Repository、@Service有何区别?
- @Componten:这个将Java类标记为bean。它是任何Spring管理组件通用构造型。spring的组件扫描机制现在可以将其拾取并将其拉入应用程序环境中。
- @Controller:这将一个类标记为Spring Web MVC控制器。标有它的Bean会自动导入到IOC容器中.
- @Service:此注解是组件注解的特化。它不会对@Component注解提供任何其他行为。您可以在服务层类中使用@Service而不是@Component,因为他以更好的方式指定了意图。
- @Repository:这个注解具有类似用途和功能的@Compoent注解的特化。它为DAO提供了额外的好处。它将DAO导入IOC容器,并使未经检查的异常有资格转化为Spring DataAccessException。
@Required注解有什么作用
这个注解表明bean的属性必须在配置的时候设置,通过一个bean定义的显示的属性值或通过自动装配,若@Required注解的bean属性未被设置,容器将抛出BeanInitialicationException。示例:
public class Employee {
rivate String name;
@Required
public void setName(String name){
this.name=name;
}
public string getName(){
return name;
}
}
@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;
}
}
@Autowired和@Resource之间的区别
- @Autowired和@Resource可用于:构造函数、成员变量、Setter方法
- @Autowired和@Resouce之间的区别在于
-
- @Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性未false)。
- @Resource默认是按照名称来装配注入的,只有当找不到于名称匹配的bean才会按照类型来装配注入
@Qualifier注解有什么作用
当您创建多个相同类型的bean并希望仅使用属性装配其中一个bean时,您可以使用@Qualifier注解和@Autowired通过指定应该装配哪个确切的bean来消除歧义。
@Autowired
@Qualifier("specificBean")
private SomeService someService;
@RequestMapping注解有什么用?
- @RequestMapping 注解用于将特定 HTTP 请求方法映射到将处理相应请求的控制器中的特定类/方法。此注释可应用于两个级别:
-
- 类级别:映射请求的 URL
-
-
- 方法级别:映射 URL 以及 HTTP 请求方法
-
Spring数据访问
解释JDBC抽象和DAO模块
通过使用JDBC抽象和DAO模块,保证数据库代码的简洁,并能避免数据库资源错误关闭导致的问题,它在不同的数据库的错误信息之上,提供了一个统一的异常访问层。它还利用了Spring的AOP模块给Spring应用中的对象提供事务管理服务。
Spring Dao有什么用?
Spring Dao(数据访问对象)使得JDBC,Hibernate或JDO这样的数据访问技术更容器以一种统一的方式工作。这是的用户容易在持久性技术之间切换。它还允许您编写代码时,无需考虑捕获每种技术不同的异常。
Spring JDBC API中存在那些类?
- jdbc Template
- SimpleJdbc Template
- NamedParamenterJdbc Template
- SimpleJdbcInsert
- SimpleJdbcCall
Sprng支持的事务管理类型,spring事务实现方式有哪些?
spring支持两种类型的事务管理:
- 编程式事务管理:这意味你通过编程的方式管理事务,给你带来极大的灵活性,但是难维护。
- 声明式事务管理:这意味着你可以将业务代码和事务管理分离,你只需要注解和xml来配置管理事务。