什么是 IOC ,了解 Spring IOC 的原理吗?
IOC/DI:控制反转,本质是将原来程序中对象创建、依赖的代码,反转交由容器去协助实现以达到统一管理对象的目的。
Spring中的IOC容器主要作用是完成对象创建、依赖管理等。
Spring IOC 原理: BeanFactory 根据配置Bean的具体 Class 通过反射调用其构造函数(默认调用无参构造函数)创建对象,
注入依赖时通过注解 @Resources(名称匹配)和@Autowired(类型匹配) 查找对应Bean,然后通过 setter 或 构造函数 方式注入。
什么是AOP,了解 Spring AOP 的原理吗?
切面编程(AOP)是通过切面非侵入式的操作程序方法,常用的场景如日志记录、权限判断、读写分离等。
Spring AOP 原理:基于动态代理技术实现,通过ProxyBeanFactory将Bean替换为其代理Bean,然后将实现MethodInterceptor接口的拦截器链注入到代理Bean中,完成方法调用拦截。
Spring支持的事务管理类型有哪些?你在项目中使用哪种方式?
Spring支持编程式事务、声明式事务管理。二者的特点是编程式事务允许通过代码控制业务、使用灵活;声明式事务配置简单、使用方便,所以在项目中更常用。
事务分为全局事务、局部事务。全局事务需要JTA支持,由于成本高、使用复杂,所以一般不在项目中使用。局部事务和底层采用的持久化方案有关,例如Mybatis通过JDBC的Connetion对象来操作事务;而Hibernate通过Session对象来操作事务。目前Spring提供了如下所示的事务管理器:
- DataSourceTransactionManager(注入DataSource)【Mybatis方案】
- HibernateTransactionManager(注入SessionFactory)
- JdoTransactionManager(管理JDO事务)
- JtaTransactionManager(使用JTA管理事务)
- PersistenceBrokerTransactionManager(管理Apache的OJB事务)
Spring MVC的工作原理是怎样的?
Spring MVC- 客户端的所有请求都交给前端控制器DispatcherServlet来处理,它会负责调用系统的其他模块来真正处理用户的请求。
- DispatcherServlet收到请求后,将根据请求的信息(包括URL、HTTP协议方法、请求头、请求参数、Cookie等)以及HandlerMapping的配置找到处理该请求的Handler(任何一个对象都可以作为请求的Handler)。
- 在这个地方Spring会通过HandlerAdapter对该处理器进行封装。
- HandlerAdapter是一个适配器,它用统一的接口对各种Handler中的方法进行调用。
- Handler完成对用户请求的处理后,会返回一个ModelAndView对象给DispatcherServlet,ModelAndView顾名思义,包含了数据模型以及相应的视图的信息。
- ModelAndView的视图是逻辑视图,DispatcherServlet还要借助ViewResolver完成从逻辑视图到真实视图对象的解析工作。
- 当得到真正的视图对象后,DispatcherServlet会利用视图对象对模型数据进行渲染。
- 客户端得到响应。
Spring MVC与Struts的区别?你会选哪个?
- Spring MVC核心控制器是Servlet,而Struts2是Filter。
- Spring Mvc会比Struts快一些(理论上)。Spring Mvc是基于方法设计,而Sturts是基于对象,每次发一次请求都会实例一个action,每个action都会被注入属性,而Spring更像Servlet一样,只有一个实例,每次请求执行对应的方法即可(注意:由于是单例实例,所以应当避免全局变量的修改,这样会产生线程安全问题)。
- Spring框架对Spring MVC支持更好,而且提供了全注解方式进行管理,各种功能的注解都比较全面,使用简单,而Struts2需要采用XML很多的配置参数来管理。
- Struts2中自身提供多种参数接受,其实都是通过(ValueStack)进行传递和赋值,而Spring MVC是通过方法的参数进行接收。
- Spring MVC相对于Struts2使用更为简单,学习成本更低。
- Struts有自己的interceptor机制,Spring MVC用的是独立的AOP方式。Spring MVC是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上Spring MVC就容易实现restful url。Struts2是类级别的拦截,一个类对应一个request上下文;实现restful url要费劲,因为Struts2 action的一个方法可以对应一个url;而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。Spring MVC的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架方法之间不共享变量,而Struts2搞的就比较乱,虽然方法之间 也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码,读程序时带来麻烦。
- Spring MVC处理ajax请求,直接通过返回数据,方法中使用注解@ResponseBody,Spring MVC自动帮我们对象转换为JSON数据。
你如何理解AOP中的连接点(Joinpoint)、切点(Pointcut)、增强(Advice)、引介(Introduction)、织入(Weaving)、切面(Aspect)这些概念?
- 连接点(Joinpoint):程序执行的某个特定位置(如:某个方法调用前、调用后,方法抛出异常后)。一个类或一段程序代码拥有一些具有边界性质的特定点,这些代码中的特定点就是连接点。Spring仅支持方法的连接点。
- 切点(Pointcut):如果连接点相当于数据中的记录,那么切点相当于查询条件,一个切点可以匹配多个连接点。Spring AOP的规则解析引擎负责解析切点所设定的查询条件,找到对应的连接点。
- 增强(Advice):增强是织入到目标类连接点上的一段程序代码。Spring提供的增强接口都是带方位名的,如:BeforeAdvice、AfterReturningAdvice、ThrowsAdvice等。很多资料上将增强译为“通知”,这明显是个词不达意的翻译,让很多程序员困惑了许久。
- 引介(Introduction):引介是一种特殊的增强,它为类添加一些属性和方法。这样,即使一个业务类原本没有实现某个接口,通过引介功能,可以动态的未该业务类添加接口的实现逻辑,让业务类成为这个接口的实现类。
- 织入(Weaving):织入是将增强添加到目标类具体连接点上的过程,AOP有三种织入方式:①编译期织入:需要特殊的Java编译期(例如AspectJ的ajc);②装载期织入:要求使用特殊的类加载器,在装载类的时候对类进行增强;③运行时织入:在运行时为目标类生成代理实现增强。Spring采用了动态代理的方式实现了运行时织入,而AspectJ采用了编译期织入和装载期织入的方式。
- 切面(Aspect):切面是由切点和增强(引介)组成的,它包括了对横切关注功能的定义,也包括了对连接点的定义。
Spring事务的传播特性了解吗?你们是如何使用的?
因为涉及到跨库操作,目前业务操作都采用的是 PROPAGATION_REQUIRES_NEW(新建事务,现有事务挂起),各Service方法事务、Connection 独立,互不影响。
在 spring的 TransactionDefinition接口中一共定义了六种事务传播属性:
- PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
- PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。
- PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。
- PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。
- PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,则抛出异常。
- PROPAGATION_NESTED -- 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
前六个策略类似于EJB CMT,第七个(PROPAGATION_NESTED)是Spring所提供的一个特殊变量。它要求事务管理器或者使用JDBC 3.0 Savepoint API提供嵌套事务行为(如Spring的DataSourceTransactionManager)
阐述Spring框架中Bean的生命周期?
- Spring IoC容器找到关于Bean的定义并实例化该Bean。
- Spring IoC容器对Bean进行依赖注入。
- 如果Bean实现了BeanNameAware接口,则将该Bean的id传给setBeanName方法。
- 如果Bean实现了BeanFactoryAware接口,则将BeanFactory对象传给setBeanFactory方法。
- 如果Bean实现了BeanPostProcessor接口,则调用其postProcessBeforeInitialization方法。
- 如果Bean实现了InitializingBean接口,则调用其afterPropertySet方法。
- 如果有和Bean关联的BeanPostProcessors对象,则这些对象的postProcessAfterInitialization方法被调用。
- 当销毁Bean实例时,如果Bean实现了DisposableBean接口,则调用其destroy方法。
网友评论