zoukankan      html  css  js  c++  java
  • Spring

    一、Spring

    1、Spring IOC、DI、AOP的理解?

    (先通俗易懂的解释下何为IOC和AOP--->各自的实现原理--->自己的项目中如何使用)

    传统应用程序示意图:

     

    有IOC/DI容器后程序示意图:

    所谓IOC,对Spring框架来说,就是由Spring来负责控制对象的生命周期和对象间的关系。传统的应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IOC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,既方便测试,又利于功能复用,更重要的是使得程序的整体结构变得非常灵活。

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

    IOC和DI是什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较模糊,所以又有了“依赖注入”。相对IOC而言,“依赖注入”明确描述了 被注入对象依赖IOC容器配置依赖对象。

    AOP是Spring框架面向切面的编程思想,Spring框架的AOP机制可以让开发者把业务流程中的通用功能抽取出来,单独编写功能代码。在业务流程执行过程中,Spring框架会根据业务流程要求,自动把独立编写的功能代码切入到流程的合适位置。比如,日志输出、事物管理、异常的处理等。

    例如,在一个业务流程系统中,用户登录是基础功能,凡是涉及到用户的业务流程都要求用户进行系统登录。如果把用户登录功能代码写到每个业务流程中,会造成代码冗余,且不方便维护。这时我们就可以将用户登录功能抽取出来,形成一个独立的模块,当业务流程需要业务登录时,系统自动把登录功能切入到流程中。

    2、Spring的优点?

    1)、Spring属于低侵入式设计,代码的污染度极低;

    2)、Spring的DI机制将对象之间的依赖关系交由框架处理,降低组件之间的耦合;

    3)、Spring提供了AOP,支持对一些通用任务,如安全、事物、日志、权限等进行集中式管理,从而提供更好的复用;

    4)、Spring支持集成主流的应用框架。

     

    3、Spring AOP的理解?

    OOP面向对象,允许开发者定义纵向的关系,但并不适用于定义横向的关系,导致了大量代码的重复,而不利于各个模块的重用。

    AOP,一般称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为切面(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事物处理。

    AOP实现的关键在于代理模式,AOP代理主要分为静态代理和动态代理。静态代理的代表主要是AspectJ;动态代理则以Spring AOP为代表。

    1)、AspectJ是静态代理的增强,所谓静态代理,就是AOP框架会在编译阶段生产AOP代理类,因此也称为编译时增强,它会在编译阶段将AspectJ(切面)织入到java字节码中,运行的时候就是增强之后的AOP对象;

    2)、Spring AOP动态代理,所谓动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。

    Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理:

      (1)JDK动态代理只提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类,InvocationHandler通过invoke()方法反射来调用目标类中的代码,动态的将横切逻辑和业务编织在一起;接着,Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象;

      (2)如果代理类没有实现InvocationHandler接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB,是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式实现动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

    3)、静态代理与动态代理的区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。

     

    4、Spring IOC的理解?

    1)、IOC就是控制反转,是指创建对象的控制权的转移。以前创建对象的主动权和时机是由自己把控的,而现在这种权利转移到Spring容器种,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。DI依赖注入,和控制反转是同一个概念的不同角度的描述,即 应用程序在运行时依赖IOC容器来动态注入对象需要的外部资源。

    2)、最直观的表达就是:IOC让对象的创建不用去new了,可以由容器自动生产,使用java的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法。

    3)、Spring IOC有三种注入方式:构造器注入、setter方法注入、根据注解注入。

    (IOC让相互协作的组件保持松散的耦合,而AOP编程允许你把遍布于应用各层的功能分离出来形成可重用的功能组件)

     

    5、BeanFactory和ApplicationContext有什么区别?

    BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。

    1)、BeanFactory:是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。ApplicationContext接口作为BeanFactory的派生,除了提供BeanFactory所具有的的功能外,还提供了更完整的架构功能:

      (1)继承MessageSource,因此支持国际化;

      (2)统一的资源文件访问方式;

      (3)提供在监听器中注册bean的事件;

      (4)同时加载多个配置文件;

      (5)载入多个(有继承关系)上下文,使得每一个上下文都专注于一个特定的层次,比如应用的web层。

    2)、

      (1)BeanFactory采用的是延迟加载形式来注入Bean的,即 只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样我们就不能发现一些存在的Spring的配置问题。如果Bean的某一属性没有注入,BeanFactory加载后,直至第一次使用调用getBean()方法才会抛出异常;

      (2)ApplicationContext是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,有利于检查依赖属性是否注入。ApplicationContext启动后预载入所有的单实例bean,确保当你需要的时候,不需要等待,因为它们已经创建好了。

      (3)相对于基本的BeanFactory,ApplicationContext唯一的不足是占用内存空间,当应用程序配置bean较多时,程序启动较慢。

    3)、BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader;

    4)、BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。

     

    6、Spring bean的生命周期?

    Spring Bean的完整生命周期从创建Spring容器开始,直到最终Spring容器销毁Bean。

    在说明前可以思考下Servlet的生命周期:实例化、初始化init、接收请求service,销毁destroy。

    Spring上下文中的Bean也类似,如下:

    1)实例化一个Bean--也就是我们常说的new;

    2)按照Spring上下文对实例化的Bean进行配置--也就是IOC注入;

    3)如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的id值;

    4)如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory方法(setBeanFactory(BeanFactory)方法传递的是Spring工厂本身,可以用这个方式来获取其他Bean,只需在Spring配置文件中配置一个普通的Bean就可以);

    5)如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文(同样这个方式也可以实现步骤4的内容,但比4更好,因为ApplicationContext是BeanFactory的子接口,有更多的实现方法);

    6)如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessorBeforeInitialization(Object obj,String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于是在Bean初始化结束时调用的方法,也可以被应用于内存或缓存技术;

    7)如果Bean在Spring配置文件中配置了init-method属性,会自动调用其配置的初始化方法;

    8)如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessorAfterInitialization(Object obj,String s)方法;

    注:以上工作完成以后就可以应用这个Bean了,这个Bean是一个Singleton的,所以一般情况下我们调用同一个id的Bean会是在内容地址相同的实例,当然在Spring配置文件中,也可以配置非Singleton的,这里我们不做赘述。

    9)当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其的destroy()方法;

    10)最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。

    以上10个步骤描述的是应用Spring上下文Bean的生命周期,如果应用Spring工厂也就是BeanFactory的话,去掉第五步就OK了。

     

    7、解释Spring支持的几种bean作用域?

    Spring容器中的bean可以分为5个范围:

    1)、singleton:默认,每个容器中只有一个bean的实例,单例模式由beanFactory自身来维护;

    2)、prototype:为每一个bean请求提供一个实例;

    3)、request:为每一个网络请求创建一个实例,在请求完成之后,bean会失效并被垃圾回收器回收;

    4)、session:与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效;

    5)、global-session:全局作用域,global-session与Portlet应用相关。当你的应用部署在Portlet容器中时,它包含很多的portlet。如果你想声明让所有的portlet共用全局的存储变量时,那么这全局变量需要存储在global-session中。全局作用域与Servlet中session作用域效果相同。

     

    8、Spring框架中的单例Beans是线程安全的吗?

    Spring框架并没有对单例Bean进行任何多线程的封装处理。关于单例Bean的线程安全和并发问题需要开发者自行去搞定。但实际上,大部分的Spring Bean并没有可变的状态(比如Service类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。如果你的bean有多种状态的话(比如View Model)对象,就需要自行保证线程安全,最浅显的解决办法就是将多态bean的作用域由“singleton”变更为“Prototype”。

     

    9、Spring如何处理线程并发问题?

    在一般情况下,只有无状态的bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域,因为spring对一些Bean中非线程安全状态采用ThreadLocal进行处理,解决线程安全问题。

    Thread Local和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采取了“时间换空间”的方式,只提供一个变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。而ThreadLocal则采用了“空间换时间”的方式,Thread Local会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量都封装进ThreadLocal。

     

    10、Spring中Bean的注入方式?

    Bean注入的方式有两种,一种是在XML中配置,分别有setter方法注入(属性注入)、构造函数注入和工厂方法注入;另一种则是使用注解的方式注入@Autowired,@Resource,@Required

    1)、属性注入:属性注入即通过setXXX()方法注入Bean的属性值或依赖对象,由于属性注入方式具有可选择性和灵活性高的优点,是实际开发中最常用的方式。

    属性注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供setter方法。Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用setter方法注入属性值。

    2)、构造方法注入:使用构造函数注入的提前是Bean必须提供带参数的构造函数。

    3)、工厂方法注入分为非静态工厂方法和静态工厂方法。

      非静态工厂方法必须实例化工厂类后才能调用,静态工厂方法无需实例化即可使用,所以静态工厂方法比非静态工厂方法调用更加方便。

    4)、使用注解方式。

     

    11、Spring的自动装配?

    在Spring中,对象无需自己查找或创建与其关联的其他对象,由容器负责把需要相互协调的对象引用赋予各个对象,使用Autowire来配置自动装载模式。

    在Spring框架xml配置中共有5种自动装配:

    1)、no:默认的方式是不进行自动装配的,通过手工设置ref属性来进行装配bean;

    2)、byName:通过bean的名称进行自动装配,如果一个bean的property与另一个bean的name相同,就进行自动装配;

    3)、byType:通过参数的数据类型进行自动装配;

    4)、constructor:利用构造函数进行装配,并且构造函数的参数通过byType进行装配;

    5)、autodetect:自动探测,如果有构造方法,通过construct的方式自动装配,否则使用byType的方式自动装配。

    基于注解的方式:

    使用@Autowired注解来自动装配指定的bean。在使用@Autowired注解之前需要在Spring配置文件进行配置,<context:annotation-config/>。在启动spring IOC时,容器自动装载了一个AutoWiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowired、@Resource或@Inject时,就会在IOC容器自动查找需要的bean,并装配给该对象的属性。在使用@Autowired时,首先在容器中查询对应类型的bean:

      如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据;

      如果查询的结果不止一个,那么@AutoWired会根据名称来查找;

      如果上述查找的结果为空,那么会抛出异常。解决方法:使用required=false。

    (@Autowired可用于:构造函数、成员变量、setter方法

     注:@Autowired和@Resource之间的区别:

        1)、@Autowired默认是按照类型装配注入的,默认情况下它要求对象必须存在(可以设置它required=false)

        2)、@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。

     

    12、Spring框架中都用到了哪些设计模式?

    1)、工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;

    2)、单例模式:Bean默认为单例模式;

    3)、代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;

    4)、模板方法:用来解决代码重复的问题。如:RestTemplate、JmsTemplate,JpaTemplate;

    5)、观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知自动更新,如Spring中listener的实现一样——ApplicationListener。

     

    13、Spring中事物的实现方式和实现原理?

    Spring事物的本质其实就是数据库对事物的支持,没有数据库的事物支持,spring是无法提供事物功能的。真正的数据库层事物的提交和回滚是通过binlog或者redo log实现的。

    1)、Spring事物的种类:

    Spring支持编程式事物管理和声明式事物管理两种方式:

    编程式事物管理使用TransactionTemplate;

    声明式事物管理建立在AOP之上的,其本质是通过AOP功能,对方法前后进行拦截,将事物处理的功能编织到拦截的方法中,也就是在目标方法开始之前加入一个事物,在执行完目标之后根据执行情况提交或者回滚事物。

    声明式事物最大的优点就是不需要在业务逻辑代码中掺杂事物管理的代码,只需在配置文件中做相关的事物规则声明或通过@Transaction注解的方式,便可以将事物规则应用到业务逻辑中。

    声明式事物管理要优于编程式事物管理,这正是Spring倡导的非侵入式的开发方式,使业务代码不受污染,只要加上注解就可以获得完全的事物支持。唯一不足的是,最细粒度只能作用到方法级别,无法做到像编程式事物那样可以作用到代码块级别。

    2)、Spring的事物传播行为:

    Spring事物的传播行为说的是,当多个事物同时存在的时候,Spring如何处理这些事物的行为。

    (1)PROPAGATION_REQUIRED:如果当前没有事物,就创建一个新事物,如果当前存在事物,就加入该事物,该设置是最常用的设置。

    (2)PROPAGATION_SUPPORTS:支持当前事物,如果当前存在事物,就加入该事物,如果当前不存在事物,就以非事物执行。

    (3)PROPAGATION_MANDATORY:支持当前事物,如果当前存在事物,就加入该事物,如果当前不存在事物,就抛出异常。

    (4)PROPAGATION_REQUIRES_NEW:创建新事物,无论当前存不存在事物,都创建新事物。

    (5)PROPAGATION_NOT_SUPPORTED:以非事物方式执行操作,如果当前存在事物,就把当前事物挂起。

    (6)PROPERATION_NEVER:以非事物方式执行,如果当前存在事物,则抛出异常、。

    (7)PRPPERATION_NESTED:如果当前存在事物,则在嵌套事物内执行,如果当前没有事物,则按REQUIRED属性执行。

    3)、Spring中的隔离级别?

    (1)ISOLATION_DEFAULT:默认隔离级别,使用数据库默认的事物隔离级别。

    (2)ISOLATION_READ_UNCOMMITTED:读未提交,允许另外一个事物可以看到这个事物未提交的数据。

    (3)ISOLATION_READ_CONNITED:读已提交,保证一个事物修改的数据提交后才能被另一事物读取,而且能看到该事物对已有记录的更新。

    (4)ISOLATION_REPEATABLE_READ:可重复读,保证一个事物修改的数据提交后才能被另一事物读取,但不能看到该事物对已有记录的更新。

    (5)ISOLATION_SERIALIZABLE:一个事物在执行过程中完全看不到其他事物对数据库所做的更新。

     

    14、Spring框架中有哪些不同类型的事件?

    1)、上下文更新事件(ContextRefreshdEvent):在调用ConfigurableApplicationContext接口中的refresh()方法时触发;

    2)、上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件;

    3)、上下文停止事件(ContextStopperedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件;

    4)、上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被注销;

    5)、请求处理事件(RequestHandledEvent):在web应用中,当一个http请求(request)结束触发该事件。如果一个bean实现了ApplicationListener接口,当一个ApplicationEvent被发布以后,bean会自动被通知。

     

    15、解释一下Spring AOP里面的几个名词?

    1)切面(Aspect):被抽取的公共模块,可能会横切多个对象。在Spring AOP中,切面可以使用通用类或者在普通类中以@AspectJ注解来实现。

    2)连接点(Join point):指方法,在Spring AOP中,一个连接点总是代表一个方法的执行。

    3)通知(Advice):在切面的某个特定的连接点上执行的动作。通知有各种类型,其中包括“around”,“before”和“after”等通知。许多AOP框架,包括Spring,都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链。

    4)切入点(Pointcut):切入点是指我们要对哪些Join point进行拦截的定义。通过切入点表达式,指定拦截的方法,比如指定拦截add*、search*等。

    5)引入(Introduction):(也被称为内部类型声明 inter-type declaration),声明额外的方法或者某个类型的字段。Spring允许引入新的接口到任何被代理的对象。例如,你可以使用一个引入来使bean实现IsModified接口,以便简化缓存机制。

    6)目标对象(Target Object):被一个或多个切面所通知的对象,也有人把它叫做被通知对象。既然Spring AOP是通过运行时代理实现的,这个对象永远是一个被代理(proxied)对象。

    7)织入(Weaving):指把增强应用到目标对象来创建新的代理对象的过程。Spring是在运行时完成织入的。

    切入点和连接点匹配的概念是AOP的关键,这使得AOP不同于其他仅仅提供拦截功能的旧技术。切入点使得定位通知(advice)可独立于OO层次。例如,一个提供声明式事务管理的around通知可以被应用到一组横跨多个对象中的方法上(例如服务层的所有业务操作)。

     

    16、Spring通知有哪些类型?

    1)前置通知(Before advice):在某连接点之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。

    2)返回后通知(After Returning advice):在某连接点正常完成后执行的通知。例如:一个方法没有抛出任何异常,正常返回。

    3)抛出异常后通知(After throwing advice):在方法抛出异常退出时执行的通知。

    4)后通知(After advice):当某连接点退出的时候执行的通知(无论是正常退出还是异常退出)。

    5)环绕通知(Around Advice):包围一个连接点的通知,如方法调用。这是最强大的一种通知类型,环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。环绕通知是最常用的一种通知类型,大部分基于拦截的AOP框架,例如Nanning和Boss4,都只提供环绕通知。

     

    17、Spring是什么?

    Spring是一个轻量级的IOC和AOP容器框架。是为java应用程序提供基础性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。常见的配置方式有三种:基于XML的配置、基于注解的配置、基于Java的配置。

    主要由以下几个模块组成:

      Spring Core:核心类库,提供IOC服务;

      Spring Context:提供框架式的Bean访问方式,以及企业级功能(JNDI、定时任务等);

      Spring AOP:AOP服务;

      Spring DAO:对JDBC的抽象,简化了数据访问异常的处理;

      Spring ORM:对现有的ORM框架的支持;

      Spring Web:提供了基本的面向web的综合特性,例如多方文件上传;

      Spring MVC:提供面向Web应用的Model-View-Controller实现。

     

    18、Spring、SpringMVC、SpringBoot理解与区别?

    https://www.jianshu.com/p/42620a0a2c33

    Spring就像是一个大家族,有众多衍生产品如Boot,Security,JPA等,但它们的基础都是Spring的IOC和AOP,IOC提供了依赖注入的容器,而AOP解决了面向切面的编程,然后在此基础上实现了其他衍生产品的高级功能;SpringMVC是基于Servlet的一个MVC框架,主要解决WEB开发问题,因为Spring的配置非常复杂,各种XML,properties处理起来比较繁琐。于是为了简化开发者的使用,Spring社区退出了SpringBoot,它遵循约定优于配置,极大降低了Spring使用门槛,但又不失Spring原本强大灵活的功能。

    三者关系如图:

    一句话总结就是:SpringMVC和SpringBoot都属于Spring,SpringMVC是基于Spring的一个MVC框架,而SpringBoot是基于Spring的一套快速开发整合包。

     

    19、说几个Spring常用的注解?

    1)@Configuration:标注在类上,表示类作为一个IoC容器,如果某个方法上标注了@Bean,就会作为这个Spring容器中的Bean;

      【@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的<beans>,其作用是配置spring容器(应用上下文);

    2)@Bean:@Bean是一个方法级别的注解,主要用在@Configuration或@Component注解的类里,等同于xml配置文件中的<bean>;

    3)@ComponentScan:该注解会默认扫描该类所在的包下所有的配置类,相当于xml文件中的<context:component-scan>;(使用value值可以指定扫描的包)

    4)@Conditional:该注解可以根据一些自定义条件动态的选择是否加载该bean到Spring IOC容器中去;

    5)@Import:通过导入的方式把实例加到Spring IOC容器中;

    6)@Autowired:是用在JavaBean中的注解,通过byType形式,用来给指定的字段或方法注入所需的外部资源;

    7)@Qualifier:Spring上下文中存在不止一个某类型的bean,会抛出异常,使用@Qualifier可以帮助我们确定bean;

    8)@Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常;

    9)@Controller:用于标注控制层组件;

    10)@Resource:默认按名称装配,当找不到与名称匹配的bean才会按类型装配;

    11)@Service:标注业务层组件;

    12)@Repository:标注数据访问层组件,即DAO层;

    13)@Lazy(true):表示延迟初始化;

     

    二、SpringMVC

    1、SpringMVC工作流程?

    1)、用户发送请求至前端控制器DispatcherServlet;

    2)、DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取handle;

    3)、处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有生成)一并返回给DispatcherServlet;

    4)、DispatcherServlet调用HandlerAdapter处理器适配器;

    5)、HandlerAdapter经过适配调用具体处理器(Handler,也叫后端控制器);

    6)、Handler执行完成返回ModelAndView;

    7)、处理器适配器(HandlerAdapter)将Handler执行结果ModelAndView返回给DispatcherServlet;

    8)、DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;

    9)、ViewResolver解析后返回具体view;

    10)、DispatcherServlet对view进行视图渲染(即将模型数据填充至视图中);

    11)、view返回渲染后的视图至DispatcherServlet;

    12)、DispatcherServlet响应用户。

     

    2、SpringMVC有哪些主要组件?

    1)、前端控制器DispatcherServlet (不需要程序员开发);

    作用:接受请求、响应结果、相当于转发器,有了DispatcherServlet就减少了其他组价之间的耦合度。

    2)、处理器映射器HandlerMapping(不需要程序员开发);

    作用:根据请求的url查找Handler。

    3)、处理器适配器HandlerAdapter;

    注意:在编写Handler的时候要按照HandlerAdapter要求的规则去写,这样适配器HandlerAdapter才能正确的执行Handler。

    4)、处理器Handler(需要程序员开发);

    5)、视图解析器ViewResolver(不需要程序员开发);

    作用:进行视图的解析,根据视图逻辑名解析成真正的视图(view)。

    6)、视图view(需要程序员开发jsp);

    注意:View是一个接口,它的实现类支持不同的视图类型(jsp、freemarker、pdf等等)。

     

    3、SpringMVC和Struts2的区别有哪些?

    1)、SpringMVC的入口是一个Servlet即前端控制器(DispatcherServlet),Struts2的入口是一个filter过滤器(StrutsPrepareAndExecuteFilter);

    2)、SpringMVC是基于方法开发(一个url对应一个方法),请求参数传递到方法形参,可以设计为单例或多例(建议单例),Struts2是基于类开发,传递参数是通过类的属性,只能设计为多例;

    3)、Struts采用值栈存储请求和响应的数据,通过OGNL(一种表达式语言)存储数据;SpringMVC通过参数解析器将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过request域传输到页面,jsp视图解析器默认使用jstl表达式。

     

    4、SpringMVC怎样设定重定向和转发的?

    1)、转发:在返回值前面加 forward,如:forward:user.do?name=xxx;

    2)、重定向:在返回值前面加 redirect,如:redirect:https://www.baidu.com。

     

    5、SpringMVC怎么和ajax交互?

    通过jackson框架就可以把java里面的对象直接转化成js可以识别的json对象。

    1)、引入Jackson.jar;

    2)、配置json映射;

    3)、在ajax方法里面可以直接返回Object,List等,但在方法前要加@ResponseBody注解。

     

    6、如何解决Post请求中文乱码问题,get呢?

    Post:在web.xml中配置一个CharacterEncodingFilter过滤器,编码设置UTF-8; 

    <filter>
    
        <filter-name>CharacterEncodingFilter</filter-name>
    
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    
        <init-param>
    
            <param-name>encoding</param-name>
    
            <param-value>utf-8</param-value>
    
        </init-param>
    
    </filter>
    
    <filter-mapping>
    
        <filter-name>CharacterEncodingFilter</filter-name>
    
        <url-pattern>/*</url-pattern>
    
    </filter-mapping>

    get:get请求中中文参数出现乱码有两个解决方法:

    1)、修改Tomcat配置文件,添加编码与工程编码一致; 

    <ConnectorURIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
    

    2)、对参数进行重新编码; 

    String userName = new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
    

    ISO8859-1是Tomcat默认编码,需要将Tomcat编码后的内容按UTF-8编码。

     

    7、SpringMVC的异常处理?

    可以将异常抛给Spring框架,由Spring框架来处理;我们只需要配置简单的异常处理器,在异常处理器中添加视图页面即可。

     

    8、SpringMVC的控制器是不是单例模式?如果是,有什么问题,怎么解决?

    是单例模式。在多线程访问的时候会有线程安全问题,但是尽量不要使用同步,会影响性能的;解决方案是在控制器里面不要写字段(不要定义全局变量)。

     

    9、SpringMVC常用的注解有哪些?

    1)、RequestMapping:用于处理请求url映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径;

    2)、RequestBody:注解实现接收http请求的json数据,将json转化成java对象;

    3)、ResponseBody:注解实现将controller方法返回的对象转化为json对象响应给客户。

     

    10、SpringMVC中控制器的注解一般使用哪个,有没有别的注解可以替代?

    一般使用@Controller,表示是表现层,不能用别的注解替代。

     

    11、如果在拦截请求中,我想拦截get方式提交的方法,怎么拦截?

    可以在@RequestMapping注解里面加上method=RequestMethod.GET。

     

    12、怎样在方法里面得到Request或者Session?

    直接在方法的形参中声明Request,SpringMVC会自动把Request对象传入。

     

    13、如果想在拦截的方法里面得到从前台传入的参数,怎么得到?

    直接在形参里面声明这个参数即可,但必须保证名字和传过来的参数一致。

     

    14、如果前台有很多个参数传入,并且这些参数都是一个对象的,怎么快速的得到这个对象?

    直接在方法中声明这个对象,SpringMVC会自动将属性赋值到这个对象里。

     

    15、SpringMVC中函数的返回值是什么?

    返回值可以有很多类型,String、ModelAndView。ModelAndView类将视图和数据合并在一起,但我们一般使用String。

     

    16、SpringMVC用什么对象从后台向前台传递数据的?

    通过ModelMap对象,可以在这个对象里面调用put方法,把对象加到里面,前台就可以通过el表达式拿到。

     

    17、怎样把ModelMap里的数据放到session里面?

    可以在类上面加上@SessionAttributes注解,里面包含的字符串就是要放入session里面的key。

     

    18、SpringMVC里面的拦截器是怎么写的?

    有两种写法,一种是实现HandlerInterceptor接口,在接口方法中,实现处理逻辑,然后在SpringMVC的配置文件中配置拦截器即可;另外一种是继承适配器类。 

    <!-- 配置SpringMvc的拦截器 -->
     
    <mvc:interceptors>
     
        <!-- 配置一个拦截器的Bean就可以了 默认是对所有请求都拦截 -->
     
        <bean id="myInterceptor" class="com.zwp.action.MyHandlerInterceptor"></bean>
     
        <!-- 只针对部分请求拦截 -->
     
        <mvc:interceptor>
     
           <mvc:mapping path="/modelMap.do" />
     
           <bean class="com.zwp.action.MyHandlerInterceptorAdapter" />
     
        </mvc:interceptor>
     
    </mvc:interceptors>
    

     

    19、注解原理?

    注解本质是一个继承了Annotation的特殊接口,其具体实现类是java运行时生成的动态代理类。我们通过反射获取注解时,返回的是java运行时生成的动态代理对象。通过代理对象调用自定义注解的方法,会最终调用AnnotationInvocationHandler的invoke方法。该方法会从memberValues这个map中检索出对应的值。而memberValues的来源是java常量池。

     

    三、SpringBoot

    1、什么是Spring Boot?

    Spring Boot是Spring开源组织下的子项目,是Spring组件一站式解决方案,主要简化了使用Spring的难度,简省了繁重的配置,提供了各种启动器,让开发者快速上手。

     

    2、为什么要使用Spring Boot?

    Spring Boot优点非常多,如:独立运行、简化配置、自动配置、无代码生成和XML配置、应用监控、上手容易...

     

    3、Spring Boot的启动过程?

    @Configuration 启动类标注了之后代表其本身是一个IOC容器的配置类;

    @ComponentScan功能就是自动扫描并加载符合条件的组件(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到IOC容器中;

    @EnableAutoConfiguration是借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IOC容器。

    其中@EnableAutoConfiguration是最重要的,借助@Import(EnableAutoConfigurationImportSelector.class)的帮助,@EnableAutoConfiguration帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器,就像一只八爪鱼一样。

    自动配置幕后英雄:SpringFactoriesLoader详解:

    借助于Spring框架原有的一个工具类:SpringFactoriesLoader的支持,@EnableAutoConfiguration可以智能的自动配置功效才得以大功告成。

    所以@EnableAutoConfiguration自动配置的魔法骑士就变成了:从classpath中搜寻所有的META-INF/spring.factories配置文件,并将对应的配置项通过反射实例化为对应的标注了@Configuration的JavaConfig形式的IOC容器配置类,然后汇总为一个并加载到IOC容器。

    深入探索SpringApplication执行流程:

    SpringApplication的run()方法的实现是我们本次旅程的主要线路,该方法的主要流程大体可以归纳如下:

    1)如果我们使用的是SpringApplication的静态run方法,那么这个方法里面首先要创建一个SpringApplication对象实例,然后调用这个创建好的SpringApplication的实例方法。在SpringApplication实例初始化的时候,它会提前做几件事情:

    • 根据classpath里面是否存在某个特征类来决定是否应该创建一个为web应用使用的ApplicationContext类型;
    • 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer;
    • 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener;
    • 推断并设置main方法的定义类。

    2)SpringApplication实例初始化完成并且完成设置后,就可以执行run方法的逻辑了,方法执行伊始,首先遍历执行所有通过SpringFactoriesLoader可以查到并加载的SpringApplicationRunListener。调用它们的started()方法,告诉这些SpringApplicationListener,“嘿,SpringBoot应用开始执行咯!”;

    3)创建并配置当前SpringBoot应用将要使用的Environment;

    4)遍历调用所有SpringApplicationRunListener的environmentPrepared()的方法,告诉它们:“当前SpringBoot应用使用的Environment准备好了”;

    5)如果SpringApplication的showBanner属性被设置为true,则打印Banner;

    6)根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前SpringBoot应用创建什么类型的ApplicationContext并创建完成,然后根据条件决定是否添加ShutdownHook,决定是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,当然,最重要的是将之前准备好的Environment设置给创建好的ApplicationContext使用;

    7)ApplicationContext创建好之后,SpringApplication会再次借助SpringFactoriesLoader,查找并加载classpath中所有可用的ApplicationContextInitializer,然后遍历调用这些ApplicationContextInitializer的initialize方法来对创建好的ApplicationContext进行进一步处理;

    8)遍历调用所有SpringApplicationRunListener的contextPrepared()方法;

    9)最核心的一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IOC容器配置加载到已经准备完毕的ApplicationContext;

    10)遍历调用所有SpringApplicationRunListener的contextLoaded()方法;

    11)调用ApplicationContext的refresh()方法,完成IOC容器可用的最后一道工序;

    12)查找当前ApplicationContext中是否注册有CommandLineRunner,如果有,则遍历执行它们;

    13)正常情况下,遍历执行SpringApplicationRunListener的finished()方法。

    3、Spring Boot的核心配置文件有哪几个?区别是什么?

    Spring Boot的核心配置文件是application和bootstrap。application主要用于Spring Boot项目的自动化配置。bootstrap主要有以下几个应用场景:

      使用Spring Cloud Config配置中心时,需要在bootstrap配置文件中添加连接到配置中心的配置属性来加载外部配置中心的配置消息;

      一些固定的不能被覆盖的属性;

      一些加密解密的场景。

     

    4、Spring Boot的配置文件有哪几种格式?有什么区别?

    .properties和.yml两种格式,区别主要是书写格式不同。

    1).properties

    app.user.name = Rain 
    

    2).yml

    app:
        user:
            name:Rain
    

    另外,.yml格式不支持@PropertySource注解导入配置。

    5、Spring Boot的核心注解是哪个?它主要有哪几个注解组成的?

    核心注解是启动类上面的@SpringBootApplication,主要包含以下三个注解:

    @SpringBootConfiguration:组合@Configuration注解,实现配置文件的功能;

    @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能:@SpringBootApplication(exclude={DataSourceAutoConfiguration.class});

    @ComponentScan:Spring组件扫描。

     

    6、开启Spring Boot特性有哪几种方式?

    1)、继承spring-boot-starter-parent项目;

    2)、导入spring-boot-dependencies项目依赖。

    https://blog.csdn.net/zl1zl2zl3/article/details/83715712

     

    7、Spring Boot需要独立的容器运行吗?

    可以不需要,内置了Tomcat/Jetty等容器。

     

    8、运行Spring Boot有哪几种方式?

    1)、打包用命令或者放到容器种运行;

    2)、使用Maven/Gradle插件运行;

    3)、直接执行main方法运行。

     

    9、Spring Boot自动配置原理是什么?

    https://blog.csdn.net/zl1zl2zl3/article/details/83715154

     

    10、如何理解Spring Boot中的Starters?

    Starters可以理解为启动器,它包含一系列可以集成到应用里面的依赖包,可以一站式集成Spring及其他技术,而不需要到处找示例代码和依赖包。如果你想使用Spring JPA访问数据库,只要加入spring-boot-starter-data-jpa启动器依赖就能使用了。

    Starters包含了许多项目中需要用到的依赖,它们能快速持续的运行,是一系列得到支持的管理传递性依赖。

    https://blog.csdn.net/zl1zl2zl3/article/details/83715784

     

    11、如何在Spring Boot启动的时候运行一些特定的代码?

    可以实现接口ApplicationRunner或者CommandLineRunner,这两个接口实现方式一样,它们都只提供了一个run方法。

    https://blog.csdn.net/zl1zl2zl3/article/details/83715818

     

    12、Spring Boot有哪几种读取配置的方式?

    Spring Boot可以通过@PropertySource、@Value、@Environment、@ConfigurationProperties来绑定变量。

    https://blog.csdn.net/zl1zl2zl3/article/details/83715873

     

    13、Spring Boot支持哪些日志框架?推荐和默认的日志框架是哪个?

    支持Java Util Logging,Log4j2,Logback作为日志框架,如果你使用Starters启动器,Spring Boot将使用Logback作为默认日志框架。

    https://blog.csdn.net/zl1zl2zl3/article/details/83715942

     

    14、Spring Boot实现热部署有哪几种方式?

    主要有两种方式:

    1)、Spring Loadad;

    2)、Spring-boot-devtools

    https://blog.csdn.net/zl1zl2zl3/article/details/83716502

     

    15、你如何理解Spring Boot配置加载顺序?

    在Spring boot里面,可以使用以下几种方式来加载配置。

    1)properties文件;

    2)YAML文件;

    3)系统环境变量;

    4)命令行参数;

    https://blog.csdn.net/zl1zl2zl3/article/details/83716564

     

     

    16、Spring Boot可以兼容老Spring项目吗?如何兼容?

    可以兼容,使用@ImportResource注解导入Spring项目配置文件。

     

    17、保护Spring Boot应用有哪些方法?

    1)在生产中使用HTTPS;

    2)使用Snyk检查你的依赖关系;

    3)升级到最新版本;

    4)使用CSRF保护;

    5)使用内容安全策略防止XSS攻击

    https://blog.csdn.net/zl1zl2zl3/article/details/83716770

     



     

  • 相关阅读:
    ubuntu下Thrift快速入门
    java Future用法和意义一句话击破 [转]
    RPC、基于netty的长连接和websocket
    基于netty的长连接
    IO
    HTML5 中websocket长连接的具体实现方法
    单链表中是否出现环状,使用快慢指针算法。
    SpringMVC 事务配置完全详解
    hibernate annotation 一对多,多对一,实例
    tomcat 内存溢出
  • 原文地址:https://www.cnblogs.com/Rain1203/p/10571918.html
Copyright © 2011-2022 走看看