Spring

使用Spring框架的好处
  1. 解耦合:

    在不使用Spring开发的项目当中,在使用相同接口的不同实现类时,每次在进行不同的实现时都要创建不同的实现类对象,而这也大大提高了对象与对象之间的耦合性,而在使用了Spring框架开发项目后,我们可以把项目当中对象的创建交给容器来管理,Spring管理实例与实例/类与类之间的依赖关系以及实例的创建,当我们要使用到不同的实现类时,只需要修改依赖注入时注入的实例bean即可

  2. 方便集成:

    Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如Struts、Hibernate、MyBatis、Quartz等)的直接支持。简化了在使用其他框架所需的冗余性代码。

  3. 轻量级:

    Spring是一个轻量级的IOC和AOP容器框架

  4. 低侵入性:

    Spring是一种非侵入式(non-invasive)框架,它可以使应用程序代码对框架的依赖最小化。

Spring和SpringBoot的区别

SpringBoot是基于Spring衍生出来的一个框架体系,是Spring本身的扩展。

  1. 使用SpringBoot完成的项目在进行线上部署时,我们只需要将打好的jar包放在类路径classpath下,然后使用java -jar运行即可,它会自动配置数据源

  2. 在创建项目时,SpringBoot会为我们提供一组预先配置好的启动项目,通过starter依赖添加到我们的项目当中

Spring IOC

Spring的两大核心思想之一

IOC(Inverse of Control:控制反转)是一种设计思想,就是 将原本在程序中手动创建对象的控制权,交由Spring框架来管理。 IoC 在其他语言中也有应用,并非 Spring 特有。 IOC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象。

将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。 IoC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。 在实际项目中一个 Service 类可能有几百甚至上千个类作为它的底层,假如我们需要实例化这个 Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,这可能会把人逼疯。如果利用 IoC 的话,你只需要配置好,然后在需要的地方引用就行了,这大大增加了项目的可维护性且降低了开发难度。

Spring AOP,动态代理

AOP(Aspect-Oriented Programming:面向切面编程),和OOP一样,它也是一种编程思想,能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,或者说为实现业务模块代码所必不可少的系统代码部分(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

Spring AOP就是基于动态代理的,如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用Cglib ,这时候Spring AOP会使用 Cglib 生成一个被代理对象的子类来作为代理。

Bean生命周期
  1. 加载配置 每个bean的配置信息,会封装为一个BeanDefinition对象

  2. 创建实例 使用Java反射机制,调用构造器,完成实例创建

  3. 执行注入

    • 属性

    • 资源 Aware接口 ,分别有:

      1. BeanFactoryAware

      2. BeanNameAware

      3. ResourceLoaderAware

      4. ApplicationContextAware

      5. ServletContextAware

      6. ServletConfigAware

  4. 初始化

    1. 初始化前执行:BeanPostProcessor接口的postProcessBeforeInitialization()方法

    2. InitializingBean接口的afterPropertiesSet()方法 (一般不会使用这种初始化,因为要实现接口,增强了类的侵入性,不符合Spring的设计思想)

    3. 自定义初始化方法

    4. 初始化后执行:BeanPostProcessor接口的postProcessAfterInitialization()方法

  5. 销毁

    1. DisposableBean接口的destroy()方法(一般不使用)

    2. 自定义销毁方法

Bean作用域?默认什么级别?是否线程安全?Spring如何保障线程安全的?
作用域
  • singleton:默认作用域,单例,每次获取都是同一个实例

  • prototype:每次请求都会创建一个新的-bean-实例

  • request:每一次http请求都会产生一个新的bean,该bean仅在当前http-request内有效

  • session:该bean仅在当前 http-session-内有效

  • global session:该bean在全局session会话范围内有效

是否线程安全

Spring中的Bean是否线程安全 和Spring无关。

  1. 因为Spring只承担了创建和管理Bean的职责,并没有对Bean进行任何修改。

  2. 因为Ioc并不具备线程安全的特性,但是要看@Scope,原型模式一定是线程安全的,因为每次都需要创建新的对象;如果单例模式的Bean是无状态的,那就是线程安全的,如果不是,则需要通过ThreadLocal来解决线程安全问题,ThreadLocal为每个线程保存了线程私有的数据,用空间来换取了时间。

解释:bean有状态就是有数据存储功能    无状态就是不会保存数据

Spring如何保障线程安全
  • Spring 的常见业务组件采取单例如何保证线程安全

    Spring 作为 IOC 框架,一般来说,Spring 管理的 controller、service、dao 都是单例存在,节省内存和 cpu、提高单机资源利用率(默认单例,配置多例模式使用 scope=prototype),既然是单例,那么如何控制单例被多个线程同时访问线程安全呢?

    首先要理解每个 http 请求到后台都是一个单独的线程,线程之间共享同一个进程的内存、io、cpu 等资源,但线程栈是线程独有,线程之间不共享栈资源

    其次,bean 分为有状态 bean 和无状态 bean,有状态 bean 即类定义了成员变量,可能被多个线程同时访问,则会出现线程安全问题;无状态 bean 每个线程访问不会产生线程安全问题,因为各个线程栈及方法栈资源都是独立的,不共享。即是,无状态 bean 可以在多线程环境下共享,有状态 bean 不能

  • Spring 的 dao、service 层使用的有状态 bean 如何保证线程安全

    Spring 应用中 dao、service 一般以单例形式存在,dao、service 中使用的数据库 connection 以及 RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder 等都是有状态 bean,而 dao、service 又是单例,如何保证线程安全呢?

    答案是使用 threadLocal 进行处理,ThreadLocal 是线程本地变量,每个线程拥有变量的一个独立副本,所以各个线程之间互不影响,保证了线程安全

Spring事务隔离级别和事务传播属性
事务传播属性(事务的传播机制)
  1. REQUIRED(默认属性)(required) 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。 被设置成这个级别时,会为每一个被调用的方法创建一个逻辑事务域。如果前面的方法已经创建了事务,那么后面的方法支持当前的事务,如果当前没有事务会重新建立事务。

  2. MANDATORY (mandatory) 支持当前事务,如果当前没有事务,就抛出异常。

  3. NEVER (never) 以非事务方式执行,如果当前存在事务,则抛出异常。

  4. NOT_SUPPORTED (not_supported) 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

  5. REQUIRES_NEW (requires_new) 新建事务,如果当前存在事务,把当前事务挂起。

  6. SUPPORTS (supports) 支持当前事务,如果当前没有事务,就以非事务方式执行。

  7. NESTED (nested) 支持当前事务,新增Savepoint点,与当前事务同步提交或回滚。 嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。

Spring事务的隔离级别
  1. DEFAULT (默认) 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应。

  2. READ_UNCOMMITTED (读未提交) 这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。

  3. READ_COMMITTED (读已提交) 保证一个事务修改的数据提交后才能被另外一个事务读取,另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。

  4. REPEATABLE_READ (可重复读) 这种事务隔离级别可以防止脏读、不可重复读,但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了不可重复读。

  5. SERIALIZABLE(串行化) 这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。除了防止脏读、不可重复读外,还避免了幻像读。

Spring以及Spring MVC常见注解

Spring常见注解

  • @Component:组件(普通的bean,三层架构中每一层都可以使用,但是不能标识该组件具体属于哪一层)

  • @Controller:控制器组件(表示该组件属于WEB层的bean)

  • @Service:业务层组件(表示该组件属于业务层的bean)

  • @Repository:数据访问层组件(表示该组件属于数据访问层的bean)

  • @Autowired:自动装配(默认按照类型自动装配),按照当前声明的接口类型自动,在容器中查找该接口的实现类对象bean,进行自动注入(装配)

  • @Qualifier:按照bean名称自动装配,与@Autowired注解配合使用。按照当前指定的bean名称,在容器中查找该名称对应的bean,进行自动注入(装配)

  • @Resource:javax扩展包提供的注解,完成自动注入,默认按照名称自动注入,也可以设置name属性按名称进行自动注入

  • @Primary:当前bean为主要bean,当发现多个相同类型的bean时,以主要bean为首选。

  • @Scope("prototype"):设置bean的作用域为每次获取时创建新实例

其中Spring MVC常见注解有:

组件型注解:

  1. @Component 在类定义之前添加@Component注解,他会被spring容器识别,并转为bean。

  2. @Repository 对Dao实现类进行注解 (特殊的@Component)

  3. @Service 用于对业务逻辑层进行注解 (特殊的@Component)

  4. @Controller 用于控制层注解 (特殊的@Component)

请求和参数型注解:

  1. @RequestMapping:用于处理请求地址映射,可以作用于类和方法上。

  2. @RequestParam:用于获取传入参数的值

  3. @PathViriable:用于定义路径参数值

  4. @ResponseBody:作用于方法上,可以将整个返回结果以某种格式返回,如json或xml格式。

@autowired和@resource的区别,当UserDao存在不止一个bean或没有存在时,会怎样?怎么解决?
  1. 提供方:@Autowired是由org.springframework.beans.factory.annotation.Autowired提供,换句话说就是由Spring提供;@Resource是由javax.annotation.Resource提供,即J2EE提供,需要JDK1.6及以上;

  2. 注入方式:@Autowired只按照类型注入;@Resource默认按名称自动注入,也提供按照类型注入;

  3. 属性:@Autowired按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false(即@Autowired(required=false))。如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。@Resource有两个中重要的属性:name和type。name属性指定byName,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。需要注意的是,@Resource如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时, @Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了。

mybatis如何防止sql注入?$和#的区别是什么?传入表明用哪个?

SQL注入是一种攻击手段,它指的是使用构造恶意的SQL语句,欺骗服务器执行SQL命令,让后台的数据库去解析,从而达到入侵目标网络,获取敏感信息的攻击手段。

mybatis中的#和$的区别
  1. 将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111", 如果传入的值是id,则解析成的sql为order by "id".

  2. 将传入的数据直接显示生成在sql中。如:order by ,如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id.

  3. 方式能够很大程度防止sql注入。利用JDBC的PreparedStatement类进行预编译。

  4. $方式无法防止Sql注入。

  5. $方式一般用于传入数据库对象,例如传入表名.

  6. 一般能用#的就别用$.

防止Sql注入

注意:SQL语句不要写成select * from t_stu where s_name like '%%',这样极易受到注入攻击。

“{xxx}”这样格式的参数会直接参与sql编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“{xxx}”这样的参数格式。 在编写mybatis的映射语句时,尽量采用“#{xxx}”这样的格式。若不得不使用“{xxx}”这样的参数,要手工地做好过滤工作,来防止sql注入攻击。

简单说,“#{}”是经过预编译的,是安全的;“${}”是未经过预编译的,仅仅是取变量的值,是非安全的,存在SQL注入。

Spring MVC工作原理

Spring框架介绍:

  • Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。

Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,可以选择是使用内置的 Spring Web 框架还是 Struts 这样的 Web 框架。通过策略接口,Spring 框架是高度可配置的,而且包含多种视图技术,例如 JavaServer Pages(JSP)技术、Velocity、Tiles、iText 和 POI。Spring MVC 框架并不知道使用的视图,所以不会强迫您只使用 JSP 技术。

Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。

  • Spring的MVC框架主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。

工作原理:

  1. 客户端请求提交到DispatcherServlet

  2. 由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller

  3. DispatcherServlet将请求提交到Controller

  4. Controller调用业务逻辑处理后,返回ModelAndView

  5. DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图

  6. 视图负责将结果显示到客户端

SpringBoot自动配置的原理是什么?介绍SpringBootApplication注解.

自动配置原理:

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。它使用“习惯优于配置”的理念可以让你的项目快速运行部署。使用Spring Boot可以不用或者只需要很少的Spring配置。

Spring Boot核心的功能就是自动配置。它会根据在类路径中的jar、类自动配置Bean,当我们需要配置的Bean没有被Spring Boot提供支持时,也可以自定义自动配置。

Spring Boot将所有的功能场景都抽取出来,做成一个个的starters(启动器),只需要在项目里面引入这些starter相关场景的所有依赖都会导入进来。要用什么功能就导入什么场景的启动器

SpringBootApplication注解:

@SpringBootApplication: Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动SpringBoot应用;被标注的类为应用的主程序类,主入口类

Mybatis和Hibernate的区别
  1. 两者最大的区别:

    Mybatis是持久层的一个“半自动化”的技术框架,而Hibernate是基于JPA实现的一个“全自动化”的持久层框架

    针对简单逻辑,Hibernate和MyBatis都有相应的代码生成工具,可以生成简单基本的DAO层方法。

    针对高级查询,Mybatis需要手动编写SQL语句,以及ResultMap。而Hibernate有良好的映射机制,开发者无需关心SQL的生成与结果映射,可以更专注于业务流程。

  2. 开发难度对比:

    Hibernate的开发难度要大于Mybatis。主要由于Hibernate比较复杂、庞大,学习周期较长。

    而Mybatis则相对简单一些,并且Mybatis主要依赖于sql的书写,让开发者感觉更熟悉。

  3. sql书写比较

    Mybatis的SQL是手动编写的,所以可以按需求指定查询的字段。不过没有自己的日志统计,所以要借助log4j来记录日志。

    Hibernate也可以自己写SQL来指定需要查询的字段,但这样就破坏了Hibernate开发的简洁性。不过Hibernate具有自己的日志统计。

  4. 数据库扩展性比较

    Mybatis由于所有SQL都是依赖数据库书写的,所以扩展性,迁移性比较差。

    Hibernate与数据库具体的关联都在XML中,所以HQL对具体是用什么数据库并不是很关心。

  5. 缓存机制比较

    相同点:Hibernate和Mybatis的二级缓存除了采用系统默认的缓存机制外,都可以通过实现你自己的缓存或为其他第三方缓存方案,创建适配器来完全覆盖缓存行为。

    不同点Hibernate的二级缓存配置在SessionFactory生成的配置文件中进行详细配置,然后再在具体的表-对象映射中配置是那种缓存。

    MyBatis的二级缓存配置都是在每个具体的表-对象映射中进行详细配置,这样针对不同的表可以自定义不同的缓存机制。并且Mybatis可以在命名空间中共享相同的缓存配置和实例,通过Cache-ref来实现。

    两者比较:因为Hibernate对查询对象有着良好的管理机制,用户无需关心SQL。所以在使用二级缓存时如果出现脏数据,系统会报出错误并提示。

    而MyBatis在这一方面,使用二级缓存时需要特别小心。如果不能完全确定数据更新操作的波及范围,避免Cache的盲目使用。否则,脏数据的出现会给系统的正常运行带来很大的隐患。

总结:

mybatis:小巧、方便、高效、简单、直接、半自动 hibernate:强大、方便、高效、复杂、绕弯子、全自动

spring中的注解原理?例如事务注解,spring如何根据注解实现事务功能的

事务功能的实现:

Spring事务管理主要包括3个接口,Spring的事务主要是由他们三个共同完成的。

1)PlatformTransactionManager:事务管理器--主要用于平台相关事务的管理

主要有三个方法:commit 事务提交;

rollback 事务回滚;

getTransaction 获取事务状态。

2)TransactionDefinition:事务定义信息--用来定义事务相关的属性,给事务管理器PlatformTransactionManager使用

这个接口有下面四个主要方法:

getIsolationLevel:获取隔离级别;

getPropagationBehavior:获取传播行为;

getTimeout:获取超时时间;

isReadOnly:是否只读(保存、更新、删除时属性变为false--可读写,查询时为true--只读)

事务管理器能够根据这个返回值进行优化,这些事务的配置信息,都可以通过配置文件进行配置。

3)TransactionStatus:事务具体运行状态--事务管理过程中,每个时间点事务的状态信息。

例如它的几个方法:

hasSavepoint():返回这个事务内部是否包含一个保存点,

isCompleted():返回该事务是否已完成,也就是说,是否已经提交或回滚

isNewTransaction():判断当前事务是否是一个新事务

Spring是依赖于传播机制来保证事务的一致性的

声明式事务的优缺点:

优点:不需要在业务逻辑代码中编写事务相关代码,只需要在配置文件配置或使用注解(@Transaction),这种方式没有侵入性。

缺点:声明式事务的最细粒度作用于方法上,如果像代码块也有事务需求,只能变通下,将代码块变为方法。

Spring中用到了哪些设计模式?单例、*、工厂、适配、观察者之类的说一说就行
  • 工厂模式 : Spring使用工厂模式通过 BeanFactoryApplicationContext 创建 bean 对象。

  • 代理模式 : Spring AOP 功能的实现。

  • 单例模式 : Spring 中的 Bean 默认都是单例的。

  • 模板方法模式 : Spring 中 jdbcTemplatehibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。

  • 包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。

  • 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。

  • 适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配Controller

  • ……

你可能感兴趣的:(Spring)