spring总结

Spring
Spring介绍:
框架:
在这里插入图片描述
Core Container(核心容器)包含有Core、Beans、Contexts 和 Expression Language模块。
Core 模块封装了框架依赖的最底层部分。主要包含Spring 框架基本的核心工具类(例如:资源访问,类型转换)。
Beans 模块是框架是所有应用都要用到的,它包含访问配置文件、创建和管理bean以及进行 Inversion of Control / Dependency Injection(IoC/DI)操作相关的所有类。
Context 模块构建于 Core 和 Beans 模块的基础之上,提供了一种类似于 JNDI 注册器的框架式的对象访问方法。Context 模块继承了 Beans 的特性,为 Spring 核心提供了大量扩展,提供了对国际化(如资源绑定)、事件传播、资源加载和对 Context 的透明创建的支持。 Context 模块同时也支持 J2EE的一些特性,例如 EJB、JMX和基础的远程处理。ApplicationContext 接口是 Context 模块的关键。
Expression Language 模块提供了一个强大的表达式语言用于在运行时查询和操纵对象。
Data Access/Interation 层包含有 JDBC、ORM、OXM、JMS 和 Transaction 模块
JDBC 模块提供了一个 JDBC 抽象层,它可以消除冗长的 JDBC 编码和解析数据库厂商特有的错误代码。此模块包含了 Spring 对 JDBC 数据访问进行封装的所有类。
ORM 模块为流行的对象-关系映射 API ,例如 JPA、JDO、 Hibernate、 iBatis等,提供了一个交互层。利用 ORM 封装包,可以混合使用 Spring 提供的特性进行 O/R映射(Object/Relation)。
Web 层包含了 Web、Web-Servlet、Web-Struts 和 Web-Porlet模块。
Web模块:提供了基础的面向 Web 的集成特性。例如,多文件上传、使用 servlet listeners 初始化 IoC 容器以及一个面向 Web 的应用上下文。它还包含 Spring 远程支持中 Web 的相关部分
Web-Servlet 模块 web.servlet.jar: 该模块包含 Spring 的 model-view-controller (MVC) 实现。 Spring 的 MVC框架使得模型范围内的代码和 web forms之间能够清楚的分离开来,并与 Spring 框架的其他特性集成在一起。
AOP 模块提供了一个符合 AOP 联盟标准的面向切面编程的实现,
Test模块支持使用 JUnit 和 TestNG 对 Spring 组件进行测试。
Bean的加载流程:
1.获取配置文件资源
2.对获取的xml资源进行一定的处理检验
3.处理包装资源
4.解析处理包装过后的资源
5.加载提取bean并注册(添加到beanDefinitionMap中)
Bean的获得流程:通过类型或者名字在前面加载的map中找出来。
特点:
1.方便解耦,简化开发
通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
2.AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。
3.声明事物的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
4.方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。
5.方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。
6.降低Java EE API的使用难度
Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。
7.Java 源码是经典学习范例
Spring的源码设计精妙、结构清晰、匠心独用,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。Spring框架源码无疑是Java技术的最佳实践范例。如果想在短时间内迅速提高自己的Java技术水平和应用开发水平,学习和研究Spring源码将会使你收到意想不到的效果。
优点:
1.低侵入式设计,代码污染极低
2.独立于各种应用服务器,基于Spring框架的应用,可以真正实现Write Once,Run Anywhere的承诺
3.Spring的DI机制降低了业务对象替换的复杂性,提高了组件之间的解耦
4.Spring的AOP支持允许将一些通用任务如安全、事务、日志等进行集中式管理,从而提供了更好的复用
5.Spring的ORM和DAO提供了与第三方持久层框架的良好整合,并简化了底层的数据库访问
6.Spring并不强制应用完全依赖于Spring,开发者可自由选用Spring框架的部分或全部
IOC/DI:
IOC(Inversion of Control,控制反转):由spring来负责控制对象的生命周期和对象间的关系。
DI(Dependency Injection,依赖注入):反射实现,由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。
实现对象之间的解耦,降低了开发难度。
Spring的IoC容器在实现控制反转和依赖注入的过程中,可以划分为两个阶段:
容器启动阶段:

  1. 加载配置文件
  2. 分析配置信息
  3. 装备的到BeanDefinition
    Bean实例化阶段:
  4. 实例化对象
  5. 装配依赖
  6. 生命周期回调
  7. 对象其他处理
  8. 注册回调接口
    Bean实例化的几种方式:
  9. 构造器初始化(无参构造器),最标准,最广泛
    bean代码:
    public class somebean {
    public somebean() {}
    }//提供一个无参的构造方法
    Xml:
  10. 静态工厂方法实例化, 解决系统遗留问题
    bean代码:
    package com.java.godv.Ioc;

class someBean1{
void say() {
System.out.println(“你好啊”);
}
}
public class someBeanStaticFactory {
public static someBean1 createBean() {
return new someBean1();//通过静态方法直接返回一个bean
}
}
Xml:
相当于我们在实例化bean的时候是通过createBean方法来的到的somebean1。
3. 实例工厂方法实例化,解决系统遗留问题.和前面一样通过方法返回对象,不过这里的方法不是静态的,是成员方法。
4. 实现FactoryBean接口实例化:实例工厂的变种
如集成MyBatis框架使用org.mybatis,spring.SqlSessionFactoryBean
bean代码:
class somebean2{
void say() {
System.out.println(“工厂变种”);
}
}
public class someBean2FactoryBean implements FactoryBean{
@Override
public somebean2 getObject() throws Exception {
return new somebean2();
}
@Override
public Class<?> getObjectType() {
return somebean2.class;
}
}
Xml:

常见的注入方式:

  1. setter方法注入(推荐)
    1.使用 bean 元素的子元素设置;
    1,常量类型,直接使用 value 赋值;

    需要注入的值

    2,引用类型,使用 ref 赋值;
    注入对象,就是把一个对象,通过 setter 方法设置给另一个对象,语法:



    3,集合类型,直接使用对应的集合类型元素即可。
    Set的注入


    set1
    set2


    List的注入


    list1
    list2


    Array的注入


    array1
    array2


    Map的注入





    Properties的注入



    pVal1
    pVal2



    2.Spring 通过属性的 setter 方法注入值;
    3.在配置文件中配置的值都是 String,Spring 可以自动的完成类型的转换
    4.属性的设置值是在 init 方法执行之前完成的
  2. 构造方法注入
    构造器方式注入使用:元素
    1,注入常量使用 value,注入对象使用 ref,注入集合使用对应的集合类型元素即可。
    2,默认情况下 constructor-arg 的顺序就是构造器参数的顺序(不建议)。
    3,调整构造器中设置参数顺序:
  3. Xml自动装配(不推荐)。
    设置:元素的:autowire 属性
    例如:
    - default:不要自动注入,缺省 default 表示 no
  • no:不要自动注入
  • byName:按照名字注入(按照属性的名字在 spring 中找 bean) factory.getBean(String beanName)
  • byType:按照依赖对象的类型注入(factory.getBean(Class requiredType))
  • constructor:按照对象的构造器上面的参数类型注入
    注意:
    1,如果按照 byName 自动注入,要求所有的属性名字和 id 的名字必须保证一种规范的命名方式;
    2,如果按照 byType 注入,如果 spring 中同一个类型有多个实例–>报 bean 不是唯一类型错误;
    两种IOC容器:
  1. BeanFactory(原始基础类型的IOC容器)
    容器在启动的时候,并不会实例化bean,只有当用户调用getBean()方法的时候才会对配置好的bean进行实例化;所以启动容器快

  2. ApplicationContext(较高级的IOC容器。推荐使用)
    当容器启动之后,容器就已经实例化好了所有配置的bean;也可以通过bean中配置来延迟初始化。
    额外功能:
    国际化支持(MessageSource) 资源访问(如URL和文件)(ResourcePatternResolver)
    事件传播(ApplicationEventPublisher)
    关系图:ApplicationContext继承自BeanFactory。所以提供了更加多的功能和方法,
    在这里插入图片描述
    IOC容器的初始化流程:
    IoC容器的初始化包括三个过程:
    第一个过程是 Resource定位 过程。这个Resource定位指的是BeanDefinition的资源定位,它由ResourceLoader通过统一的Resource接口来完成,这个Resource对各种形式的BeanDefinition的使用都提供了统一接口。比如.在文件系统中的Bean定义信息可以使用FileSystemResource来进行抽象。在类路径中的Bean定义信息可以使用ClassPathResource来进行抽象等等。这个定位过程类似于容器寻找数据的过程,就像用水捅装水先要把水找到一样。
    第二个过程是 BeanDefinition的载入 。这个载入过程是把用户定义好的Bean表示成IoC容器内部的数据结构,而这个容器内部的数据结构就是BeanDefinition。下面介绍这个数据结构的详细定义。具体来说,这个BeanDefinition实际上就是POJO对象在IoC容器中的抽象。通过这个BeanDefinition定义的数据结构,使IoC容器能够方便地对Polo对象也就是Bean进行管理。
    第三个过程是 向IoC容器注册这些Bean Definition 的过程。这个过程是通过调用BeanDefinitionRegistry接口的实现来完成的。这个注册过程把载人过程中解析得到的BeanDeftnition向IoC容器进行注册。在IoC容器内部将BeanDefinition注人到一个Map中去,IoC容器就是通过这个Map来持有这些BeanDefinition数据的。
    Bean的生命周期:
    大致来说:执行Bean的构造器创建实例为bean注入属性->调用bean的属性指定的初始化方–》容器初始化成功,执行正常的调用–》调用bean的方法销毁。
    IOC注解实现和XML实现:

AOP:
我们在使用aop时。只用Spring提供给开发者的jar包是不够的,还需要下载两个jar包:1、aopalliance.jar 2、aspectjweaver.jar .
AOP(Aspect Oriented Programming),即面向切面编程,OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
AOP把软件系统分为两个部分:核心关注点和横切关注点。
概念:
1、横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
2、切面(aspect):类是对物体特征的抽象,切面就是对横切关注点的抽象
3、连接点(joinpoint):被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
4、切入点(pointcut):对连接点进行拦截的定义
5、通知(advice):所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类
6、目标对象:代理的目标对象
7、织入(weave):将切面应用到目标对象并导致代理对象创建的过程
8、引入(introduction):在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。代理规则为:两种混合使用。如果被代理对象实现了接口,就优先使用JDK代理,如果没有实现接口,就用用cglib代理。可以进行配置强制使用哪一种。
<aop:config proxy-target-class=“true”>
注意使用cglib动态代理需要导入两个jar包,asm-5.2.jar,cglib-3.2.5.jar。
AOP编程,我们只需要:
1、定义普通业务组件
2、定义切入点,一个切入点可能横切多个业务组件
3、定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作
AOP的XML配置:
//通知:植入的代码
<aop:config proxy-target-class=“true”>//强制cglib代理模式。默认jdk
<aop:aspect ref=“txmanager”>//配置切面
<aop:pointcut expression=“execution(* com.java.godv.AOP.Service.(…))” id=“txpoint”/>// expression表达式。在那些类上
//在切入点的那些部分执行哪些方法。
<aop:before method=“begin” pointcut-ref=“txpoint”/>
<aop:after-returning method=“commit” pointcut-ref=“txpoint”/>
<aop:after-throwing method=“back” pointcut-ref=“txpoint” throwing=“ex”/>
</aop:aspect>
</aop:config>
注解配置:
package com.java.godv.AOP.annotate;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component//组件注解
@Aspect//配置切面
//事务管理器
public class Manager {
@Pointcut(“execution(* com.java.godv.AOP.annotate.Service.(…))”)
public void txpoint() {

}
@Before("txpoint()")
public void begin() {
	
	System.out.println("开启事务");
}
@AfterThrowing(value="txpoint()",throwing="ex")
public void back(Throwable ex) {
	System.out.println("回滚事务"+ex.getMessage());
}
@AfterReturning("txpoint()")
public void commit() {
	System.out.println("提交事务");
}

}
细节:

Execution表达式:
execution(<修饰符模式>? <返回类型模式> <方法名模式>(<参数模式>) <异常模式>?)
<aop:pointcut expression=“execution(* com.java.godv.AOP.Service.(…))” id=“txpoint”/> 匹配以service结尾的包及其子包。
匹配所有类public方法 execution(public * (…))
匹配指定包下所有类方法 execution(
com.baidu.dao.(…)) 不包含子包
execution(
com.baidu.dao…(…)) …表示包、子孙包下所有类
匹配指定类所有方法 execution(
com.baidu.service.UserService.
(…))
匹配实现特定接口所有类方法
execution(* com.baidu.dao.GenericDAO+.(…))
匹配所有save开头的方法 execution(
save*(…))
事务:
事务管理的方法都是在service层的。
声明式事务:通过注解和XML配置类管理事务。管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

编程式事务:通过编写代码来管理事务。允许用户在代码中精确定义事务的边界。即类似于JDBC编程实现事务管理。管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。
一般事务的xml配置

<bean id="dataSource"
	class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
	<property name="url" value="${jdbc.url}" />
	<property name="username" value="${jdbc.username}" />
	<property name="password" value="${jdbc.password}" />
	<property name="driverClassName" value="${jdbc.driver}" />
	<property name="maxActive" value="10" />
	<property name="minIdle" value="5" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">//配置JDBC和Mybatis的事务管理器
	<property name="dataSource" ref="dataSource" />
</bean>
<!-- 通知 -->
<tx:advice id="txAdvice"
	transaction-manager="transactionManager">
	<tx:attributes>
		<!-- 传播行为。When -->
		<tx:method name="save*" propagation="REQUIRED" />
		<tx:method name="insert*" propagation="REQUIRED" />
		<tx:method name="add*" propagation="REQUIRED" />
		<tx:method name="create*" propagation="REQUIRED" />
		<tx:method name="delete*" propagation="REQUIRED" />
		<tx:method name="update*" propagation="REQUIRED" />
		<tx:method name="find*" propagation="SUPPORTS"
			read-only="true" />
		<tx:method name="select*" propagation="SUPPORTS"
			read-only="true" />
		<tx:method name="get*" propagation="SUPPORTS"
			read-only="true" />
	</tx:attributes>
</tx:advice>
<!-- 切面 where -->
<aop:config>
	<aop:advisor advice-ref="txAdvice"
		pointcut="execution(* cn.e3mall.service.*.*(..))" />
</aop:config>

关于spring事务的三个重要接口:
PlatformTransactionManager:Springa事务机制是一种典型的策略模式,PlatformTransactionManager代表事务管理接口,但它并不知道到底如何管理事务,它只要求事务管理提供开始事务getTransaction(),提交事务commit()和回滚事务rollback()这三个方法,但具体如何实现则交给其实现类完成。
1):TransactionStatus getTransaction(TransactionDefinition definition):根据事务定义信息从事务。环境中返回一个已存在的事务,或者创建一个新的事务。
2):void commit(TransactionStatus status):根据事务的状态提交事务,如果事务状态已经标识为rollback-only,该方法执行回滚事务的操作。
3):void rollback(TransactionStatus status):将事务回滚,当 commit 方法抛出异常时,rollback 会被隐式调用
使用 Spring 管理事务的时候,首先得告诉 Spring 使用哪一个事务管理器
TransactionDefinition:封装事务的隔离级别和超时时间,是否为只读事务和事务的隔离级别和传播规则等事务属性。
TransactionStatus:封装了事务的具体运行状态。如是否是新开启事务,是否已经提交事务,设置当前事务为 rollback-only 等。
前面的都是spring做的事情。我们需要配置一个事务管理器。交给spring
对于事务管理器:
DataSourceTransactionManager:支持 JDBC,MyBatis;
HibernateTransactionManager:支持 Hibernate;
事务的传播规则:一个事务方法中调用其他的事物方法,此时的事物该如何传播。按照神恶魔规则传播,用谁的事务,等等规则
Spring提供了7中规则
情况一:遵从当前事务
REQUIRED必须存在事务,如果当前存在一个事务,则加入该事务,否则将新建一个事务(缺省)。
SUPPORTS:支持当前事务,指如果当前存在逻辑事务,就加入到该逻辑事务,如果当前没有逻辑事务,就以非事务方式执行。
MANDATORY 必须有事务,使用当前事务执行,如果当前没有事务,则抛出异常
IllegalTransactionStateException。
情况二:不遵从当前事务
REQUIRES_NEW:不管当前是否存在事务,每次都创建新的事务
NOT_SUPPORTRD :以非事务方式执行,如果当前存在逻辑事务,就把当前事务暂停,以非事务方式执行。
NEVER:不支持事务,如果当前存在是事务,则抛出异常,IllegalTransactionStateException
情况三:寄生事务(外部事务和寄生事务)
NESTED :寄生事务,如果当前存在事务,则在内部事务内执行,如果当前不存在事务,则创建一个新的事务,嵌套事务使用数据库中的保存点来实现,即嵌套事务回滚不影响外部事务,但外部事务回滚将导致嵌套事务回滚。
DataSourceTransactionManager 默认支持寄生事务,而 HibernateTransactionManager 默认不支持,需要手动设置。
事务方法的属性配置:
属性 是否必须 缺省值 描述
Name 是 事务管理那个方法,可使用*通配符
Propagation 否 REQUIRED 事务传播规则
Isolation 否 DEFAULT 事务隔离级别。一般使用DEFAULT。
默认使用底层数据库的隔离级别。
Read-only 否 FALSE 事务是否只读。一般查询设置为只读。提高效率
Timeout 否 -1 事务超时时间,默认-1 由底层数据库的系统决定
no-rollback-for 否 运行时异常和error 需要回滚的异常类型。可自己设置异常类型
rollback-for 否 检查类型异常 不需要回滚的数据类型。可自己设置异常类型

Spring事务的执行流程;
获取对应事务属性,也就是获取@Transactional注解上的属性
获取TransactionManager,常用的如DataSourceTransactionManager事务管理
在目标方法执行前获取事务并收集事务信息
回调执行下一个调用链。
一旦出现异常,尝试异常处理
提交事务前的事务信息清理。
提交事务。
源码详解:
1、 事务配置信息主要是通过拦截器和Spring AOP发生作用的, 如图:
在这里插入图片描述
监听器TransactionAttributeSourceAdvisor通过正则匹配,将事务方法的属性配置以Properties的形式读入到TransactionAttributeSource中,然后TransactionAttributeSource又通过setTransactionAttribute()方法将事务封装成TransactionAttribute对象并将事务方法和对应的对象信息存储到nameMap中。

2、监听器TransactionAttributeSourceAdvisor中依赖一个拦截器TransactionInterceptor,这个拦截器管理事务的具体操作:

    TransactionInterceptor通过invoke方法读取执行方法的事务信息,并读取TransactionManager事务管理类配置进行事务处理, 

    加入读取的TransactionManager事务管理类为DataSourceTransactionManager,他根据配置的数据源信息DataSource连接数据源,并根据事务的配置信息进行事务的创建、挂起、提交和回滚。同时生成对象TransactionStatus进行保存事务处理的基本信息。 


  TransactionStatus和拎一个事物对象TransactionInfo共同作用,决定底层事务的具体实现,TransactionInfo中封装了处理事务的配置信息及TransactionStatus对象,并通过ThreadLocal技术和当前线程进行绑定:创建新事务时,如果当前线程中有事务--1、如果事务的传播属性为never,那么会抛出异常;2、如果传播属性为Propagation_not_support,则将事务挂起;3、传播属性为Propagation_requires_new,创建新事务,同事将线程中存在的事务挂起。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值