Spring有哪些特色?前端
使用Spring有什么好处?java
1 应用解耦mysql
2 依赖注入git
3 AOPweb
4 事务管理spring
5 MVCsql
6 集成开发数据库
Spring应用程序看起来像什么?apache
一些接口及其实现编程
一些POJO类
一些xml配置文件
Spring核心容器模块是什么?
Spring core/IOC/BeanFactory
核心容器(Spring Core)
核心容器提供Spring框架的基本功能。Spring以bean的方式组织和管理Java应用中的各个组件及其关系。Spring使用BeanFactory来产生和管理Bean,它是工厂模式的实现。BeanFactory使用控制反转(IoC)模式将应用的配置和依赖性规范与实际的应用程序代码分开。
为了下降Java开发的复杂性, Spring采起了哪几种策略
POJO/IOC/AOP/Template
基于POJO的轻量性和最小侵入性编程
经过依赖注入和面向接口实现松耦合
基于切面和惯例进行声明式编程
经过切面和模板减小样板式代码
谈谈Spring框架几个主要部分组成
Spring core/beans/context/aop/jdbc/tx/web mvc/orm
说一下Spring中支持的bean做用域
Singleton/prototype/request/session
singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例。
prototype:原型模式,每次经过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例。
request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不一样的Bean实例。只有在Web应用中使用Spring时该做用域才有效。
session:对于每次HTTP Session,使用session定义的Bean都将产生一个新实例。一样只有在Web应用中使用Spring时该做用域才有效。
Spring框架中单例beans是线程安全的吗?为何?
不是线程安全(默认singleton)
当多个线程并发执行该请求对应的业务逻辑(成员方法),若是该处理逻辑中有对单例状态的修改(单例的成员属性),则必须考虑线程同步问题。
解释Spring框架中bean的生命周期
哪些是最重要的bean生命周期方法?能重写它们吗?
Setup/teardown
Xml中对应Init-method/destory-method
@PostConstruct @PreDestory
bean标签有两个重要的属性(init-method 和 destroy-method),能够经过这两个属性定义本身的初始化方法和析构方法。Spring也有相应的注解:@PostConstruct 和 @PreDestroy。
Spring容器实例化Bean有多少种方法?分别是什么?
使用类构造器
使用静态工厂方法
Xml配置文件factory-method
如何减小Spring XML的配置数量
使用Java配置文件,使xml中的bean转为Javaconfig文件方式
注解的方式
什么是bean自动装配?并解释自动装配的各类模式?
Spring容器能够自动配置相互协做beans之间的关联关系。这意味着Spring能够自动配置一个bean和其余协做bean之间的关系,经过检查BeanFactory 的内容里没有使用和< property>元素。
一个类就是一个Bean,Spring框架是一个Bean容器,替咱们管理这些Bean,Spring就是来组织各个角色之间的关系,而后对这些角色进行调动。
自动装配:
自动装配有哪些好处和坏处?
自动装配的优势以下:
虽然自动装配具备上面这些优势,但不是说何时均可以使用它,由于它还有以下一些缺点:
是否是全部类型都能自动装配?若是不是请举例
不是。原生类型/字符串类型不能够自动装配
什么是循环依赖?
循环依赖就是N个类中循环嵌套引用,若是在平常开发中咱们用new 对象的方式发生这种循环依赖的话程序会在运行时一直循环调用,直至内存溢出报错。
public class PersonA { private PersonB personB; public PersonA(PersonB personB) { this.personB = personB; } } public class PersonB { private PersonC personC; public PersonB(PersonC personC) { this.personC = personC; } } public class PersonC { private PersonA personA; public PersonC(PersonA personA) { this.personA = personA; } }
Spring如何解决循环依赖?
DefaultSingletonBeanRegistry.getSingleton源码中有3个cache:
getSingleton()的整个过程,Spring首先从一级缓存singletonObjects中获取。若是获取不到,而且对象正在建立中,就再从二级缓存earlySingletonObjects中获取。若是仍是获取不到且容许singletonFactories经过getObject()获取,就从三级缓存singletonFactory.getObject()(三级缓存)获取。
解析:
PersonA的setter依赖了PersonB的实例对象,同时PersonB的setter依赖了PersonA的实例对象”这种循环依赖的状况。
PersonA首先完成了初始化的第一步,而且将本身提早曝光到singletonFactories中,此时进行初始化的第二步,发现本身依赖对象PersonB,此时就尝试去get(PersonB),发现PersonB尚未被create,因此执行create流程,PersonB在初始化第一步的时候发现本身依赖了对象PersonA,因而尝试get(PersonA),尝试一级缓存singletonObjects(确定没有,由于A还没初始化彻底),尝试二级缓存earlySingletonObjects(也没有),尝试三级缓存singletonFactories,因为PersonA经过ObjectFactory将本身提早曝光了,因此PersonB可以经过ObjectFactory.getObject拿到PersonA对象(虽然PersonA尚未初始化彻底),PersonB拿到PersonA对象后顺利完成了初始化阶段一、二、3,彻底初始化以后将本身放入到一级缓存singletonObjects中。此时返回PersonA中,PersonA此时能拿到PersonB的对象顺利完成本身的初始化阶段二、3,最终A也完成了初始化,进去了一级缓存singletonObjects中。并且,因为PersonB拿到了PersonA的对象引用,因此PersonB如今中的PersonA对象完成了初始化。
SpringMVC的工做流程和原理是什么?
SpringMVC与Struts2的主要区别?
区别1:
Struts2 的核心是基于一个Filter即StrutsPreparedAndExcuteFilter
SpringMvc的核心是基于一个Servlet即DispatcherServlet(前端控制器)
区别2:
Struts2是基于类开发的,传递的参数是经过类的属性传递(属性驱动和模型驱动),因此只能设计成多例prototype
SpringMvc是基于类中的方法开发的,也就是一个url对应一个方法,传递参数是传到方法的形参上面,因此既能够是单例模式也能够是多例模式singiton
区别3:
Struts2采用的是值栈存储请求以及响应数据,OGNL存取数据
SpringMvc采用request来解析请求内容,而后由其内部的getParameter给方法中形参赋值,再把后台处理过的数据经过ModelAndView对象存储,Model存储数据,View存储返回的页面,再把对象经过request传输到页面去。
SpringMVC的控制器是否是单例模式,若是是有什么问题,怎么解决
是。单例若是有非静态成员变量保存状态会有线程安全问题。
解决办法1:不要有成员变量,都是方法。
解决办法2:@Scope(“prototype”)
Spring注解的基本概念和原理
注解(Annotation),也叫元数据。一种代码级别的说明。
Spring注解分为:
1.类级别的注解:如@Component、@Repository、@Controller、@Service以及JavaEE6的@ManagedBean和@Named注解,都是添加在类上面的类级别注解。
Spring容器根据注解的过滤规则扫描读取注解Bean定义类,并将其注册到Spring IoC容器中。
2.类内部的注解:如@Autowire、@Value、@Resource以及EJB和WebService相关的注解等,都是添加在类内部的字段或者方法上的类内部注解。
SpringIoC容器经过Bean后置注解处理器解析Bean内部的注解。
举例说明什么是Spring基于Java的配置?
Spring3.0以前都是基于XML配置的,Spring3.0开始能够几乎不使用XML而使用纯粹的java代码来配置Spring应用。
@Configuration @EnableTransactionManagement public class AppConfig implements TransactionManagementConfigurer { @Bean public DruidDataSource dataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl("jdbc:mysql://localhost:3306/sqoop"); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUsername("root"); dataSource.setPassword("abcd_123"); return dataSource; } @Bean public JdbcTemplate jdbcTemplate(DruidDataSource dataSource) { return new JdbcTemplate(dataSource); } @Bean public PlatformTransactionManager txManager() { return new DataSourceTransactionManager(dataSource()); } @Override public PlatformTransactionManager annotationDrivenTransactionManager() { return txManager(); } }
什么是基于注解的容器配置?
XML解耦了配置和原代码,而注解则精简了配置。spring框架基于注解的容器配置:
@Qualifier
@Autowired
@Resource
@PostContuct
@PreDestory
@Autowired @Resource @Inject 的区别
@Resource
一、@Resource是JSR250规范的实现,须要导入javax.annotation实现注入。
二、@Resource是根据名称进行自动装配的,通常会指定一个name属性
三、@Resource能够做用在变量、setter方法上。
@Autowired
一、@Autowired是spring自带的,@Inject是JSR330规范实现的,@Resource是JSR250规范实现的,须要导入不一样的包
二、@Autowired、@Inject用法基本同样,不一样的是@Autowired有一个request属性
三、@Autowired、@Inject是默认按照类型匹配的,@Resource是按照名称匹配的
四、@Autowired若是须要按照名称匹配须要和@Qualifier一块儿使用,@Inject和@Name一块儿使用
什么是AOP,有什么做用,能应用在什么场景?
面向切面编程。
AOP主要做用
将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,经过对这些行为的分离,咱们但愿能够将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
总之,面向切面的目标与面向对象的目标没有不一样。一是减小重复,二是专一业务。
AOP应用场景
日志记录,性能统计,安全控制,事务处理,异常处理等问题及扩展
什么是织入,织入的时机是什么
把切面(aspect)链接到其它的应用程序类型或者对象上,并建立一个被通知(advised)的对象,这样的行为叫作织入。
织入操做能够发生在以下几个阶段。
编译期织入是指在Java编译期,将切面织入到Java类中;而类加载期织入则指经过特殊的类加载器,在类字节码加载到JVM时,织入切面;运行期织入则是采用CGLib工具或JDK动态代理进行切面的织入
什么是切入点,关注点,链接点
链接点(JoinPoint) spring容许你是通知(Advice)的地方,基本每一个方法的前、后、环绕或抛出异常时均可以是链接点,spring只支持方法链接点。其余如AspectJ还可让你在构造器或属性注入时都行。
切入点(Pointcut) 一个类里,有N个方法就有N个链接点,可是你并不想在全部方法上都使用通知,只想让其中几个方法执行前、后或者抛出异常完成其余功能(如日志,性能分析),那么就用切入点来筛选到那几个你想要的方法。
public class BusinessLogic { public void doSomething() { // 验证安全性;Securtity关注点 // 执行前记录日志;Logging关注点 doit(); // 保存逻辑运算后的数据;Persistence关注点 // 执行结束记录日志;Logging关注点 } }
Business Logic属于核心关注点,它会调用到Security,Logging,Persistence等横切关注点。
Spring提供了几种AOP支持?
方式一:经典的基于代理的AOP
方式二:@AspectJ注解的切面
方式三:纯POJO切面
AOP经常使用的实现方式有两种,一种是采用声明的方式来实现(基于XML),一种是采用注解的方式来实现(基于AspectJ)。
举例说明什么是事物以及其特色
事务是为了保证对同一数据表操做的一致性。
Java EE事务类型有哪些?应用场景是什么?Spring是如何实现的?
通常J2EE服务器支持三种类型的事务管理。即:JDBC事务,JTA事务,容器管理事务。
JDBC事物接口:PlatformTransactionManager、AbstractPlatformTransactionManager、DataSourceTransactionManager
JTA具备三个主要的接口:UserTransaction、JTATransactionManager、Transaction接口
容器级事务主要是由容器提供的事务管理,如:WebLogic/Websphere
Spring有几个事物隔离级别,分别详述
事务隔离级别(5种)
DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。
未提交读(read uncommited) :脏读,不可重复读,虚读都有可能发生。
已提交读 (read commited):避免脏读。可是不可重复读和虚读有可能发生。
可重复读 (repeatable read) :避免脏读和不可重复读.可是虚读有可能发生。
串行化的 (serializable) :避免以上全部读问题。
Mysql 默认:可重复读
Oracle 默认:读已提交
read uncommited:是最低的事务隔离级别,它容许另一个事务能够看到这个事务未提交的数据。
read commited:保证一个事物提交后才能被另一个事务读取。另一个事务不能读取该事物未提交的数据。
repeatable read:这种事务隔离级别能够防止脏读,不可重复读。可是可能会出现幻象读。它除了保证一个事务不能被另一个事务读取未提交的数据以外还避免了如下状况产生(不可重复读)。
serializable:这是花费最高代价但最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读以外,还避免了幻象读(避免三种)。
描述下SpringJDBC的架构
Spring JDBC提供了一套JDBC抽象框架,用于简化JDBC开发。
Spring主要提供JDBC模板方式、关系数据库对象化方式、SimpleJdbc方式、事务管理来简化JDBC编程。
support包:提供将JDBC异常转换为DAO非检查异常转换类、一些工具类如JdbcUtils等。
datasource包:提供简化访问JDBC 数据源(javax.sql.DataSource实现)工具类,并提供了一些DataSource简单实现类从而能使从这些DataSource获取的链接能自动获得Spring管理事务支持。
core包:提供JDBC模板类实现及可变部分的回调接口,还提供SimpleJdbcInsert等简单辅助类。
object包:提供关系数据库的对象表示形式,如MappingSqlQuery、SqlUpdate、SqlCall
描述下Spring事务处理类及其做用
Spring框架支持事务管理的核心是事务管理器抽象,对于不一样的数据访问框架(如Hibernate)经过实现策略接口PlatformTransactionManager。该接口由3个方法组成:
getTransaction():返回一个已经激活的事务或建立一个新的事务(根据给定的TransactionDefinition类型参数定义的事务属性),返回的是TransactionStatus对象表明了当前事务的状态,该方法抛出TransactionException(未检查异常)表示事务因为某种缘由失败。
commit():用于提交TransactionStatus参数表明的事务
rollback():用于回滚TransactionStatus参数表明的事务
编程式事务
一、直接使用PlatformTransactionManager实现
二、使用TransactionTemplate模板类,用于支持逻辑事务管理。
声明式事务
一、AOP代理方式实现
二、@Transactional实现事务管理
<tx:annotation-driven transaction-manager="transactionManager"
Spring提供几种事物实现?分别是什么?各有什么优缺点?
一种编程式和三种声明式
一种编程式(基于底层 API txManager.getTransaction方式或基于TransactionTemplate)
三种声明式:AOP(TransactionProxyFactoryBean),基于AspectJ的声明式事务<tx:advice>,基于注解方式的声明式事务(@Transactional)编程式事务侵入性比较强,但处理粒度更细。
JdbcTemplate有哪些主要方法
CRUD操做所有包含在JdbcTemplate
ResultSetExtractor/RowMapper/RowCallbackHandler
JdbcTemplate支持哪些回调类
一、RowMapper是一个精简版的ResultSetExtractor,RowMapper可以直接处理一条结果集内容,而ResultSetExtractor须要咱们本身去ResultSet中去取结果集的内容,可是ResultSetExtractor拥有更多的控制权,在使用上能够更灵活;
二、与RowCallbackHandler相比,ResultSetExtractor是无状态的,他不可以用来处理有状态的资源。
什么是MyBatis?简述MyBatis的体系结构
Mybatis的功能架构分为三层:
列举MyBatis的经常使用API及方法
org.apache.ibatis.session.SqlSession
MyBatis工做的主要顶层API,表示和数据库交互的会话。完毕必要数据库增删改查功能。
org.apache.ibatis.executor.Executor
MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护。
org.apache.ibatis.executor.statement.StatementHandler
封装了JDBC Statement操做。负责对JDBC statement 的操做。如设置參数、将Statement结果集转换成List集合。
org.apache.ibatis.executor.parameter.ParameterHandler
负责对用户传递的参数转换成JDBC Statement 所需要的参数。
org.apache.ibatis.executor.resultset.ResultSetHandler
负责将JDBC返回的ResultSet结果集对象转换成List类型的集合
org.apache.ibatis.type.TypeHandler
负责java数据类型和jdbc数据类型之间的映射和转换
org.apache.ibatis.mapping.MappedStatement
MappedStatement维护了一条<select|update|delete|insert>节点的封装
org.apache.ibatis.mapping.SqlSource
负责依据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回
org.apache.ibatis.mapping.BoundSql
表示动态生成的SQL语句以及对应的参数信息
org.apache.ibatis.session.Configuration
MyBatis所有的配置信息都维持在Configuration对象之中
对于Hibernate和MyBatis的区别与利弊,谈谈你的见解
一、hibernate真正掌握要比mybatis难,由于hibernate的功能和特性很是多,还不适合多表关联查询。
二、hibernate查询会将全部关联表的字段所有查询出来,会致使性能消耗,固然hibernate也能够本身写sql指定字段,但这就破坏了hibernate的简洁性。mybatis的sql是本身手动编写的,因此能够指定查询字段。
三、hibernate与数据库管联只需在xml文件中配置便可,全部的HQL语句都与具体使用的数据库无关,移植性很好;mybatis全部的sql都是依赖所用数据库的,因此移植性差。
四、hibernate是在jdbc上进行一次封装,mybatis是基于原生的jdbc,运行速度较快。
五、若是有上千万的表或者单次查询或提交百万数据以上不建议使用hibernate。若是统计功能、多表关联查询较多较复杂建议使用mybatis。
#{}和${}的区别是什么?
select * from location where id = ${id} => Select * from location where id = xxx;
Select * from location where id = #{} => Select * from location where id="xxxx";
${}方式没法防止sql注入;
Order by动态参数时,使用${}而不用#{}
模糊查询的时候使用${}
select * from location where name like '${}%';
Mybatis是如何进行分页的?分页插件的原理是什么?
RowBounds针对ResultSet结果集执行分页
<select id="selectById" parameterType="int" resultType="com.dongnao.demo.dao.Location"> select * from location where id = #{id} </select>
插件分页
@Intercepts
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,而后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
简述Mybatis的插件运行原理,以及如何编写一个插件
Mybatis仅能够编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件。
Mybatis使用JDK的动态代理,为须要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法。固然,只会拦截那些你指定须要拦截的方法。
实现Mybatis的Interceptor接口并复写intercept()方法,而后在给插件编写注解,指定要拦截哪个接口的哪些方法便可。记住,别忘了在配置文件中配置你编写的插件。
Mybatis动态sql是作什么的?都有哪些动态sql?简述一下动态sql的执行原理
Mybatis动态sql可让咱们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能。
Mybatis提供了9种动态sql标签trim|where|set|foreach|if|choose|when|otherwise|bind
原理为,使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。
动态SQL,主要用于解决查询条件不肯定的状况:在程序运行期间,根据提交的查询条件进行查询。
动态SQL,即经过MyBatis提供的各类标签对条件做出判断以实现动态拼接SQL语句。
Mybatis是否支持延迟加载?若是支持,它的实现原理是什么?
Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,能够配置是否启用延迟加载lazyLoadingEnabled=true|false。
它的原理是,使用CGLIB建立目标对象的代理对象。当调用目标方法时,进入拦截器方法,如:调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,而后调用a.setB(b),因而a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。
Mybatis的Xml映射文件中,不一样的Xml映射文件,id是否能够重复?
能够。Mybatis namespace+id
Mybatis都有哪些Executor执行器?它们之间的区别是什么?
SimpleExecutor执行一次sql,开始建立一个statement,用完关闭statement
ReuseExector 相似数据库链接池,statement用完后返回,statement能够复用
BatchExecutor主要用于批处理执行
Mybatis是否能够映射Enum枚举类?
能够。Mybatis能够映射枚举类,不单能够映射枚举类,Mybatis能够映射任何对象到表的一列上。
Mybatis可否执行一对1、一对多关联查询?都有哪些实现方式,它们之间有什么区别
能,Mybatis不只能够执行一对1、一对多的关联查询,还能够执行多对一,多对多的关联查询。
什么是MyBatis的接口绑定,有什么好处
接口映射就是在IBatis中任意定义接口,而后把接口里边的方法和SQL语句绑定,咱们能够直接调用接口方法,比起SqlSession提供的方法咱们能够有更加灵活的选择和设置。
iBatis和MyBatis在细节上的不一样有哪些
区别太多,篇幅太长,你们能够自行百度下。
讲下MyBatis的缓存
MyBatis 提供了查询缓存来缓存数据,以提升查询的性能。MyBatis 的缓存分为一级缓存和二级缓存。
一级缓存是 SqlSession 级别的缓存
二级缓存是 mapper 级别的缓存,多个 SqlSession 共享
一级缓存
一级缓存是SqlSession级别的缓存,是基于HashMap的本地缓存。不一样的 SqlSession之间的缓存数据区域互不影响。
一级缓存的做用域是SqlSession范围,当同一个SqlSession执行两次相同的 sql语句时,第一次执行完后会将数据库中查询的数据写到缓存,第二次查询时直接从缓存获取不用去数据库查询。当SqlSession执行insert、update、delete 操作并提交到数据库时,会清空缓存,保证缓存中的信息是最新的。
MyBatis默认开启一级缓存。
二级缓存
二级缓存是mapper级别的缓存,一样是基于HashMap进行存储,多个SqlSession能够共用二级缓存,其做用域是mapper的同一个namespace。不一样的SqlSession两次执行相同的namespace下的sql语句,会执行相同的sql,第二次查询只会查询第一次查询时读取数据库后写到缓存的数据,不会再去数据库查询。
MyBatis 默认没有开启二级缓存,开启只需在配置文件中写入以下代码:
<settings> <setting name="cacheEnabled" value="true"/> </settings>