Spring3.X学习笔记

IOC==DI 依赖注入
让调用类对某一接口实现类的依赖关系由第三方(容器或协作类)注入
注入方式:
构造函数注入或属性注入
属性注入可以有选择的通过Setter方法完成调用类所需依赖的注入
Spring通过配置文件或注解描述类和类之间的依赖关系,自动完成类的初始化和依赖注入的工作。
Spring利用了类的反射功能,仅凭一个配置文件,就可实例化并装配好程序所用的Bean
Spring设计了一个Resource接口,它为应用提供了更强的访问底层资源的能力。使用Resource装载各种资源,如配置文件资源、国际化属性文件等。可以在脱离Spring框架下使用。
类路径和文件系统的的路径,具体是什么意思??
Bean的生命周期
1、Bean的作用范围
2、实例化Bean时所经历的一系列阶段
Bean的作用域
Spring 1.0 仅支持singleton和prototype
scope="作用域类型",默认是singleton
singleton:在Spring IOC容器中仅存在一个Bean实例,Bean实例以单实例的方式存在
prototype:每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行new XxxBean()的操作。
Spring容器将prototype的Bean交给调用者后,就不再管理它的生命周期了。
以下作用域仅适用于WebApplicationContext环境:
request:每次Http请求都会创建一个新的Bean
session:同一个Http Session共享一个Bean,不同 Http Session 使用不同的Bean.
globalSession:同一个全局Session共享一个Bean,通常用于Portlet应用环境。Portlet??
实现Bean定义信息,基于XML、基于注解、基于java类这三种选项,还允许多项自由的组合而非取此舍彼。
Spring容器成功启动的三大要件分别是:Bean定义信息、Bean实现类以及Spring本身。
注解:@Component(beanname),以下和@Component等效的注解。
@Repository:用于对DAO实现类进行标注。
@Service:用于对Service实现类进行标注。
@Controller:用于对Controller实现类进行标注。
@PostConstruct 指定初始化方法
@PreDestroy 指定销毁方法
@Lazy
@Autowired 默认按类型匹配的方式,在容器查找匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入到@Autowired标注的变量中。
使用@Qualifier指定注入Bean的名称。
@Scope,显式指定Bean的作用范围。
基于Java类的配置,必须保证有
@Configuration,将一个POJO标注定义为Bean的配置类,意为可用于为Spring提供Bean的定义信息。本身已经标注了@Component注解,所以任何标注了@Configuration
的类,本身也相当于标注了@Component,也可以被当成普通的Bean一样被注入到其他的Bean中。
@Bean,提供一个Bean的定义信息,Bean的类型由方法返回值类型决定,名称默认和方法名相同。也可通过入参显示指定,如@Bean(name="userDao")
通常使用基于XML+基于注解的配置方式
Spring容器高级主题
Spring源码:接口层描述了容器的主要组件及组件间的协作关系。继承体系逐步实现组件的各项功能。
BeanDefinition <bean>
org.springframework.beans.factory.config.BeanDefinition
Spring容器通过BeanDefinition将配置文件中的<bean>配置信息转换为容器的内部表示。
InstantiationStrategy 策略接口
org.springframework.beans.factory.support.InstantiationStrategy
负责根据BeanDefinition对象创建一个Bean实例,实例化Bean,相当于new的功能。
BeanWrapper
org.springframework.beans.BeanWrapper
相当于一个代理器,通过BeanWrapper完成Bean属性的填充工作
属性编辑器
实现 java.beans.PropertyEditor接口的类都是属性编辑器。
将外部的设置值转换为JVM内部的对应类型,所以属性编辑器其实就是一个类型转换器。
JavaBean的编辑器
Spring环境下使用的属性编辑器的功能非常单一:仅需要将配置文件中字面值转换为属性类型的对象即可。
根据JavaBeans的规范,JavaBeans的基础设施会在JavaBean相同类包下查找是否存在<JavaBean>Editor类,如果存在,自动使用<JavaBean>Editor作为该JavaBean的ProppertyEditor.
如UserEditor会自动成为User的属性编辑器,Spring也支持这个规范
引入properties文件,在Spring配置文件中使用如${driverClassName}等引用properties中键值对
org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
  p:location="classpath:jdbc.properties"
  p:fileEncoding="UTF-8"/>
或通过context命名空间定义属性文件,不能直接设置utf-8,需要将utf-8声明为一个字符串的Bean
<context:property-placeholder location="classpath:jdbc.properties" file-encoding="utf8"/>
<bean id="utf8" class="java.lang.String">
  <constructor-arg value="utf-8"/>
</bean>
DES加密解密工具类
信息的加密分类对称和非对称两种方式
对称:加密后的信息可以解密成原值 如DES
不对称:加密后的信息不能解密成原值 如MD5
引用Bean的属性值
国际化信息
 本地化信息,需要“语言类型”和“国家/地区的类型”,
 java通过java.util.Locale表示一个本地化对象,允许通过语言参数和国家/地区参数创建一个确定的本地化对象。是创建国际化的基础
语言参数有两个小写字母表示。如中文:zh,英语:en国家/地区的类型有两个大写字母表示.如中国CN,美国US。
资源名_语言代码_国家/地区代码.properties
使用native2ascii命令转换为Unicode代码
java提供了用于加载本地化资源文件的方便类java.util.ResourceBoundle
Spring定义了访问国际化信息的MessageSource接口,并提供了几个易用的实现类。
ApplicationContext就实现了MessageSource接口,将国际化信息作为容器的公共基础设施对所有组件开放。
native2ascii [-reverse] [-encoding 编码] [输入文件[输出文件]] 通常IDE工具有属性编辑器的插件,不需要再另外转换
--Spring AOP基础
AOP:面向切面编程,是作为OOP面向对象编程的有益补充。
AOP一般适用于那些具有横切逻辑的应用场合,如性能监测、访问控制、事务管理以及日志记录。
性能监视和事务管理的代码就好像一个圆木的年轮,而业务代码是圆木的核心,这也正是横切代码概念的由来。
将独立的逻辑融合到业务逻辑中完成和原来一样的业务操作,才是关键,也正是AOP要解决的主要问题。
AOP相关术语
1.连接点(Joinpoint)
程序执行的某个特定位置:如类开始初始化前、类初始化后、类某个方法调用前、调用后、方法抛也异常后。一个类或一段代码拥有一些具有边界性质的特定点,这些代码中的特定点就称为“连接点”。
Spring仅支持方法连接点,即仅能在方法调用前、方法调用后,方法抛出异常时这些程序执行点织入增强。
2.切点(Pointcut) org.springframework.aop.Pointcut 使用类和方法作为连接点的查询条件
每个程序类中都拥有多个连接点,如一个类中有两个方法,这两个方法都是连接点,即连接点是程序类中客观存在的事务。
AOP通过"切点"定位特定连接点。
连接点相当于数据库中的记录,而切点则相当于查询条件,切点和连接点不是一对一的关系,一个切点可以匹配多个连接点。
3.增强(Advice)执行逻辑,执行点的方位
增强是织入到目标类连接点上的一段程序代码。
结合执行点方位信息和切点信息,就可以找到特定的连接点了。
增强即包含了用于添加到目标连接点上的一段执行逻辑,又包含了用于定位连接点的文件信息。
4.目标对象(Target)
增强逻辑的织入目标类。
5.引介(Introduction)
引介是一种特殊的增强,它为类添加一些属性和方法。这样即使一个业务类原本没有实现某个接口,通过AOP的引介功能,我们可以动态的为该业务类添加接口的实现逻辑,让业务类成为这个接口的实现类。
6.织入(Weaving)
织入是将增强添加对目标类具体连接点上的过程,AOP像一个织布机,将目标类、增强或者引介通过AOP这台织布机天衣无缝的织到一起。
AOP三种织入方式
1)编译期织入:这要求使用特殊的JAVA编译器
2)类装载期织入:这要求使用特殊的类装载期
3)动态代理织入:在运行期为目标类添加增强生成子类的方式。
Spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。
7.代理(Proxy)
一个类被AOP织入增强后,就产生了一个结果类,它是融合了原类和增强逻辑的代理类,调用方式和调用原类相同的方式。
8.切面(Aspect) Advisor
切面由切点和增强(引入)组成,将切面所定义的横切逻辑织入到切面所指定的连接点中。
第一:如何通过切点和增强定位到连接点上。
第二:如何在增强中编写切面的代码。
AspectJ是语言级的AOP实现。
AspectWerkz 基于Java的简单、动态、轻量级的AOP框架。AspectJ和AspectWerkz已经合并,第一个版本是AspectJ5,扩展AspectJ语言,以基于注解的方式支持类似AspectJ的代码风格。
JBossAOP
Spring AOP 纯JAVA实现,在运行期通过代理方式向目标类织入增强代码。侧重于提供一种和Spring IOC容器整合的AOP实现。在Spring中,可以无缝的将Spring AOP,IOC,和AspectJ整合在一起。
Spring AOP 使用了两种代理机制:一种是基于JDK的动态代理;另一种是基于CGLib的动态代理。JDK只提供接口的代理,不提供类的代理。
JDK动态代理
主要涉及到java.lang.reflect包中的Proxy和InvocationHandler
InvocationHandler是一个接口,可以通过实现接口定义横切逻辑,并通过反射机制调用目标类的代码。
Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理。
JDK动态代理只能为接口创建代理,这一点我们可以从Proxy的接口newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)的方法签中看出来。
CGLib动态代理
采用底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,并顺势织入横切逻辑。
按照增强在目标类方法的连接点位置,分类以下5类:
前置增强:org.springframework.aop.BeforeAdvice代表前置增强,MethodBeforeAdvice
后置增强:org.springframework.aop.AfterReturningAdvice ,目标方法执行后增强。
环绕增强:org.springframework.intercept.MehodInterceptor.目标方法执行前后实施增强。
异常抛出增强:org.springframework.aop.ThrowsAdvice
引介增强:org.springframework.aop.IntroductionInterceptor.表示在目标类中添加一些新的方法和属性。
ProxyFactory org.springframework.aop.framework.ProxyFactory
ProxyFactory内部就是使用JDK代理或CGLib代理的技术,将增强应用到目标类中。
CGLib创建代理时速度慢,而创建出的代理对象运行效率较高,而使用JDK代理的表现正好相反。
切点类型:
1)静态方法切点 org.springframework.aop.support.StaticMethodMatherPointcut
2)动态方法切点 org.springframework.aop.support.DynamicMethodMatcherPointcut 已过时,可使用DefaultPointcutAdvisor
3)注解切点 org.springframework.aop.support.annotation.AnnotationMatchingPointcut
4)表达式切点 org.springframework.aop.support.ExpressionPointcut 接口为了支持AspectJ切点表达式语法而定义的接口
5)流程切点: org.springframework.aop.support.ControlFlowPointcut 根据执行堆栈的信息查看目标方法是否由某一个方法直接或间接发起调用,以此判断是否为匹配的连接点,性能慢。
6)复合切点: org.springframework.aop.support.ComposablePointcut 实现类为创建多个切点而提供的方便操作类。它所有的方法都返回ComposablePointcut.
定义动态切点,如果将getClassFilter()和matches(Method method,Class clazz)注释掉,每次调用代理对象的任何一个方法,都会执行
 动态切点检查,这将导致很大的性能问题,所以在定义动态切点时切勿忘记覆盖这两个方法。
 静态切面和动态切面都是通过动态代理技术实现的。
 静态切面是指在生成代理对象时,就确定了增强是否需要织入到目标类连接点上。
 动态切面必须在运行期根据方法入参的值来判断增强是否需要织入到目标类连接点上。
 
 自动创建代理
 BeanPostProcessor 的实现类
 org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator 允许为一组特定配置名的Bean自动创建代理实现的代理创建器。
 org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator:它会对容器中所有的Advisor进行扫描,自动将这些切面应用到匹配的Bean中。
 第七章 基于@AspectJ和Schema的AOP
 Spring AOP 包括了基于XML Schema配置的AOP 和基于@AspectJ注解的AOP,虽然配置切面时的表现方式不同,但底层都是采用动态代理技术(JDK代理或CGLib代理),
 Spring可以集成AspectJ,但AspectJ并不是Spring的范畴。
 注解不会直接影响程序的运行,但是第三方程序或工具可以利用代码中的注解间接控制程序的运行。
 使用@AspectJ,JDK版本要是5.0以上。
 AspectJ 5 的表达式由关键字和操作参数组成,如execution(* greetingTo(..))的切点表达式,execution为关键字,而"* greeingTo(..)"为操作参数。
 execution 代表目标类执行某一方法,"* greeingTo(..)"描述目标方法的匹配模式串。两者连接起来表示greetingTo方法的连接点。
 在函数入参中使用通配符
 * 表示匹配任意字符,但它只能匹配上下文中的一处元素。
.. 匹配任意字符,作为入参可单独使用,表示类时,要和*联合使用
+ 表示按类型匹配指定类的所有类,必须跟在类名后面,如com.baobaotao.Car+,继承或扩展指定类的所有类,同时还包括指定类本身。
不同增强类型
@Before 前置增强 相当于BeforeAdvice
value 该成员用于定义切点,argNames 成员。
@AfterReturning 后置增强 相当于AfterReturningAdvice
value 和 pointcut 定义切点,同时定义 pointcut将覆盖value
returning 将目标对象的方法返回值绑定给增强的方法
argNames 成员。
@Around 环绕增强 相当于MethodInterceptor
value 该成员用于定义切点,argNames 成员。
@AfterThrowing 相当于ThrowsAdvice
value 和 pointcut 定义切点,同时定义 pointcut将覆盖value
throwing 将抛出的异常绑定到增强方法中
@After 无论是正常退出还是抛出异常都会执行
@DeclareParents 引介增强 相当于IntroductionInterceptor
value 该成员用于定义切点
defalutImpl 默认的接口实现类。
argNames 成员。
切点函数详解
@annotation 标注了某个注解的所有方法,如@AfterReturning("@annotation(com.baobaotao.anno.NeedTest)") 方法标注了@NeedTest就可以使用这个定义的切面。
execution
args()和@args()
args(com.baobaotao.Waiter) 表示运行时入参是Waiter类型的方法 等价于execution(* *(com.baobaotao.Waiter+)) 也等价于args(com.baobaotao.Waiter+)
@args()热受一个注解类的类名。
within() 所指定的连接点的最小范围是类,没有execution的范围大。
@target 匹配标注了注解的目标类
@within 匹配标注了注解的目标类以及子孙类,不适用于接口。
target(M) 若目标类按类型匹配于M,则目标类所有方法匹配切点,如定义接口类,则其实现类中的所有方法匹配切点。 等价于this(M),不同的在于引介界面
基于Schema的配置
基于@AspectJ注解的切面,本质上是将切点、增强类型的信息使用注解进行描述,现在把这个信息放到Schema的XML配置文件中,只是配置信息所在的地方不一样,表达的信息完全可以做到相同。
<aop:config><aop:pointcut><aop:aspect><aop:before><aop:after-returning><aop:around><aop:after-throwing><aop:after>Final增强<aop:declare-parents>引介增强
advisor是Spring切面概念的对应物,是切点和增强的复合体,不过仅包含一个切点和一个增强。在AspectJ中没有对应的等价物,在aop Schema中可以通过<aop:advisor>配置一个advisor.
4种定义切面的方式
基于@AspectJ注解的方式
基于<aop:aspect>的方式
基于<aop:advisor>的方式
基于Advisor类的方式
JVM CLASS 文件字节码转换基础知识
LTW:LOAD TIME WEAVING 我们所接触的AOP切面织入都是在运行期通过JDK代理或CFLib代理的方式实现的,实际上除了运行期织入切面的方式外,还可以在类加载期通过字节码编辑的技术,将切面织入到目标类中。
java.lang.instrument包的工作原理
Instrumentation:代表JVM内部的一个构件。“组件”
ClassFileTransformer:class文件转换器接口。
第2篇:Spring数据访问
Spring对DAO的支持
Spring 的事务管理
使用Spring JDBC 访问数据库
整合其他ORM框架
Spring对DAO的支持
Spring DAO异常体系
Spring数据访问模板
配置数据源
DAO Data Access Object 用于访问数据的对象。
Spring针对不同持久化技术对应的模板类
JDBC JdbcTemplate
Hibernate 3.0 HibernateTempleate 其他就不一一列举了
持久化技术的支持类
JdbcDaoSupport
HibernateDaoSupport
配置数据源
其一是Apache的AOP;其二是C3P0。
MySql如果发现一个连接的空闲时间超过8小时,将会在数据库端自动关闭这个连接
DBCP数据源
class="org.springframework.commons.dbcp.BasicDataSource" destroy-method="close"
C3P0数据源
class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"
close方法可以保证Spring容器关闭时数据源能够成功释放。
获取JNDI数据源 JndiObjectFactoryBean,应用服务器(WebLogic或Websphere等)本身提供的数据源.
Spring的数据源实现类 DriverManagerDataSource
org.springframework.jdbc.datasourc.DriveManagerDataSource 它并没有提供池化连接的机制.适合在单元测试或简单的独立应用中使用,因为他不需要额外的依赖类.
9.Spring的事务管理
数据库基础知识
数据库事务:一荣俱荣,一损俱损,很多的事务要分步执行,但是它们组成一个整体,要么整体生效,要么整体失效.反应到数据库上就是多个SQL语句,要么所有执行成功,要么所有执行失败.
具体4个特性:原子性,一致性 隔离性 持久性.简称为ACID.
原子性:表示组成一个事务的多个数据库操作是一个不可分割的原子单元,只有所有的操作执行成功,整个事务才提交.否则回滚.
一致性:事务操作成功后,数据库所处的状态和它的业务规则是一致的.既数据不会被破坏.
隔离性:在并发数据操作时,不同的事务拥有各自的数据空间,它们的操作不会对对方产生干扰.数据库规定了多种隔离级别,级别越高,数据一致性越好,但并发性越弱.
持久性:一旦事务提交成功后,事务中所有的数据操作都必须被持久化到数据库中,即使事务提交后,数据库马上崩溃,在数据库重启时,也必须保证能够通过某种机制恢复数据.
数据一致性是最终目标.
数据并发的问题
一个数据库可能拥有多个访问客户端,这些客户端都可用并发的方式访问数据库.数据库中的相同数据可能同时被多个事务访问,如果没有采取必要的隔离措施,就会导致各种并发问题,破坏数据的完整性.
脏读(dirty read):A事务读取B事务尚未提交的更改数据,并在这个基础上操作.如果恰巧B事务回滚则A事务读到的数据肯定是错误的.在Oracle数据库中,不会发生脏读的情况.
不可重复读(unrepeatable read):A事务读取了B事务已经提交的更改数据,A事务在不同的时间点读取的数据不一致.
幻像读(phantom read):A事务读取B事务提交的新增数据,这时A事务将出现幻像读的问题.一般发生在计算统计数据的事务中,如:银行系统在同一个事务中,两次统计存款账户的总金额,在两次
统计过程中,刚好新增了一个存款账户,并存入100元,这时两次读取的总金额不一致.如果新增数据刚好满足了事务的查询条件,这个新数据将进入事务的视野,因面产生了两次统计不一致的情况.
与不可重复读的区别:
不可重复读:读到了已经提交事务的更改数据(更新或删除).对策:对操作的数据添加行级锁.
幻像读:读到了其他已经提交事务的新增数据. 对策:将整个表锁定,防止新增数据.
第一类丢失更新:A事务的撤消,把B事务已经执行成功的操作给覆盖.
第二类丢失更新:A事务覆盖B事务已经提交的数据,造成B事务所做操作丢失.
Oracle数据库常用的5种锁定
行共享锁定,行独占锁定,表共享锁定,表共享行独占,表独占.
事务隔离级别
因为数据库为用户提供了自动锁机制,只要用户指定会话的事务隔离级别,数据库就会分析事务中的SQL语句,然后自动为事务操作的数据资源添加上合适的锁.
4种事务隔离级别
隔离级别 脏读 不可重复读 幻象读 第一类丢失更新 第二类丢失更新
READ UNCOMMITED 允许 允许 允许 不允许 允许
READ COMMITED 不允许 允许 允许 不允许 允许
REPEATABLE READ 不允许 不允许 允许 不允许 不允许
SERIALIZABLE 不允许 不允许 不允许 不允许 不允许
事务的隔离级别和并发性是对立的,隔离级别越低的,并发性越高.
Jdbc对事务的支持
可能通过Connection#getMetaData()方法获取DatabaseMetaData对象,并通过该对象的supportsTransactions() supportsTransationIsolationLever(int level)查看底层数据库的事务支持情况.
因为Connection是自动提交的,一个Sql认为是一个事务,所以要setAutoCommit(false),关闭Connection的自动提交功能.
可以使用保存点Savepoint,指定回滚到保存点,不是所有的数据库都支持,DatebaseMetaDate#supportsSavePoints()查看是否支持保存点.
ThreadLocal基础知识 java.lang.ThreadLocal
非线程安全的资源,不能在同一时刻被多个线程共享.
ThreadLocal不是一个线程,而是线程的一个本地化对象,当工作于多线程中的对象使用ThreadLocal维护变量时,ThreadLocal为每个使用该变更的线程分配一个独立的变量副本.所以每一个线程可以独立地改变自己的副本.
void set(Object value) 设置当前线程的线程局部变量的值;
public Object get() 返回当前线程所对应的线程局部变量的值;
public void remove() 将当前线程局部变量的值删除.加快内存回收速度
protected Object initialValue() 返回该线程局部变量的初始值,为了让子类覆盖面设计的.
JDK 5.0后支持泛型,ThreadLocal<T>,ThreadLocal中有一个Map,键为线程对象,值为对应线程的变量副本.
ThreadLocal和线程同步都是为了解决多线程中相同变量的访问冲突问题.
线程同步"以时间换空间",访问串行化,对象共享化,仅提供一份变量,让不同的线程排队访问;
ThreadLocal "以空间换时间",访问并行化,对象独享化;对每一个线程提供一份变量,因此可以同时访问而不受影响;
Spring 对事务管理的支持
事务模板类 TransactionTemplate并配合使用TransactionCallback指定具体的持久化操作就可以通过编程方式实现事务管理.
声明式事务管理,允许通过声明方式,在IOC配置中指定事务的边界和事务属性,Spring自动在特定的事务边界上应用事务属性.
SPI(Service Provider Interface) org.springframework.transaction 包
TransactionDefinition定义了Spring兼容的事务属性
事务隔离,事务传播,事务超时 超时的话事务将被回滚,只读事务
TransactionStatus 事务状态
PlatformTransactionManager
Spring 的事务管理器实现类
Spring将事务管理提交给底层具体的持久化实现框架完成.为不同的持久化框架提供了PlatformTransactionManager
Hibernate:org.springframework.orm.hibernate3.HiberanteTrancationManager ,使用Hibernate3.0版本进行持久化,使用该事务管理器.
jdbc或ibatis:org.springframework.jdbc.datasource.DataSourceTransactionManager
org.springframework.transaction.jta.JtaTransactionManager 具有多个数据源的全局事务使用该事务管理器(不管采用何种持久化技术)
要实现事务管理,需要在Spring中配置好相应的事务管理器,并指定数据资源以及一些其他的事务管理控制属性
事务同步管理器 TransactionSynchronizationManager
Spring将JDBC的Connection Hibernate的Session等访问数据库的连接或会话对象统称为资源.
Spring Hibnerate 3.0 SessionFactoryUtils
Spring JDBC或ibatis DataSourceUtils
事务传播行为 7种 多个事务方法相互调用时,事务如何在这些方法间传播.
PROPAGATION_REQUIRED 如果当前没有事务就新建一个事务,如果当前已经存在一个事务,就加入到这个事务中,(最常见的选择)
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务就以非事务运行.
PROPAGATION_MANDATORY 使用当前事务,如果当前没有事务就抛出异常.
PROPAGATION_REQUIRED_NEW 新建一个事务,如果当前存在一个事务,就将这个事务挂起.
PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果当前存在一个事务,就将这个事务挂起.
PROPAGATION_NEVER 以非事务方式运行,如果当前存在一个事务,就抛出一个异常
PROPAGATION_NESTED 如果当前没有事务,则在嵌套事务内执行,如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作.(要求底层数据源,必须基于JDBC3.0,并且实现者需要支持保存点机制)
通过Spring声明式事务配置让业务方法拥有适合的事务功能.
基于aop/tx配置声明式事务管理是实际应用中最常使用的事务管理方式,它的表达能力最强且使用最为灵活.
使用注解配置声明式事务
@Transactional 对业务类(或方法处)进行事务增强的标注 有自己的属性的.
<tx:annotation-driven transaction-manager="txManager"/>
Spring的事务管理难点剖析
使用Hibernate事务管理器后,可以混合使用Hibernate和Spring JDBC数据访问技术,它们将工作于同一事务上下文中.共用一个连接.但是使用Spring JDBC访问数据时,Hibernate的一级或二级缓存
得不到同步,此外,一级缓存延迟数据同步机制可能会覆盖Spring JDBC数据更改的结果."事务同步面缓存不同步"
不能被Spring AOP事务增强的方法(不能启动事务)
基于接口的动态代理,除public外的所有方法,此外public static方法也不能被增强
基于CGLib的动态代理,private ,static,final方法
不同数据访问框架DataSourceUtils的等价类
Spring JDBC或iBatis org.springframework.jdbc.datasource.DataSourceUtils
Hibernate org.springframework.orm.hibernate3.SessionFactoryUtils
数据源代理,可以防止数据泄露,以便使数据源拥有感知事务上下文的能力.
Spring JDBC或iBatis org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy
Hibernate org.springframework.orm.hibernate3.LocalSessionFactoryBean
Spring JDBC
由于JdbcTemplate是线程安全的,所有DAO都可以共享一个JdbcTemplate实例.
不同数据库获取新增加的主键值
DB2 IDENTITY_VAL_LOCAL()
MySql SELECT LAST_INSERT_ID()
ORACLE 不提供自增键,提供序列 SELECT <SEQUENCE_NAME> nextval FROM DUAL 获取下一个值.
批量更改数据
JdbcTemplate两个批量数据操作的方法
public int[] batchUpdate(String[] sql)
int[] batchUpdate(String sql,BatchPreparedStatementSetter ps)
使用RowCallbackHandler处理结果集 org.springframework.jdbc.core.RowCallbackHandler 回调接口 void processRow(ResultSet rs)throws SQLException
使用RowMapper<T>处理结果集 T mapRow(ResultSet rs,int rowNum) 更适合在多行结果集中使用.
RowMapper将所有的结果集查询出来,返回一个List,若数据量过大的时候会占用很多的JVM内在.
如向用户发送邮件,若使用RowMapper,如果有100万个User,则会先查找出100万个用户,再逐个发送邮件,内存中会有100万个用户.若使用RowCallbackHandler,则可以获取到用户的时候就调用发送邮件的动作.
查询单值数据
如 String sql="select count(*) from t_forum"; queryForInt(sql)
调用存储过程 JdbcTemplate 并配合使用CallableStatementCallback
<T>T execute(String callString,CallableStatementCallback<T> action) callString指定调用存储过程的Sql语句,CallableStatementCallback 回调接口
CallableStatementCallback 方法T doInCallableStatement(CallableStatement cs)
<T> T execute(CallableStatementCreator csc,CallableStatementCallback<T> action)
BLOB/CLOB 类型数据的操作 (大对象数据)
不同数据源的本地JDBC对象抽取器类.
C3P0数据源 org.springframework.jdbc.support.nativejdbc.C3P0NativeJdbcExtractor
获取JDBC本地对象,Spring在org.springframework.jdbc.support.nativejdbc包下定义NativeJdbcExtractor接口并提供实现类.
BLOB 用于存储大块的二进制数据,如图片数据,视频数据等.
CLOB 用于存储长文本数据,如论坛的帖子内容,产器的详细描述等.
Spring提供了以下两个接口类操作大对象数据.
LobCreator 一个线程只能操作一个Lob数据 ,写入数据
LobHandler 接口为操作大二进制字段和大文本字段提供了统一访问接口访问.还充当LobCreator的工厂类.(OracleLobHandler ,其它数据库DefaultLobHandler) 读取数据
以流数据方式读取Lob数据 AbstractLobStreamingResultSetExtractor
自增键和行集
DataFieldValueIncrementer
 新建表控制主键,主键通过另外个表控制 incrementerName 表名 columnNam控制主键的列表 cacheSize 一次缓存的个数
 <bean id="incre" class="org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer" p:dataSource-ref="dataSource"
 p:incrementerName="t_post_id" p:columnName="sequence_id" p:cacheSize="10" /><!--应用层主键方案>
 数据层主键方案:主键分配由数据库负责,在表结构定义时,将主键列设置为auto_increment或者通过表的触发器分配主键.
如何规划主键方案
采用UUID(是一个36位的字符串),缺点:会占用很多的存储空间.
分段长整型,如将一个主键分成三段,地区设备类型设备序号.
如果应用是集群部署的,所有集群节点都通过同一序列表获取主键值,就必须对这个序列表进行乐观锁定.
以行集返回数据
SqlRowSet 一次性装载所有的匹配数据
其他类型的JdbcTemplate
NamedParameterJdbcTemplate 可以根据名称设置参数
SimpleJdbcTemplate 过期
 以OO(面向对象方式)访问数据库
使用MappingSqlQuery访问数据库,父类SqlQuery是一个可重用 ,线程安全的类.
使用SqlUpdate更新数据
使用StoredProcedure执行存储过程
  整合其他ORM框架
在Spring中使用Hibernate Spring3.0仅对Hibernate3.x支持
使用Hibernate 1编写Hibernate的配置文件 2使用配置文件实例化SessionFactory
Spring为创建SessionFactory提供了org.springframework.orm.hibernate3.LocalSessionFactoryBean
使用HibernateTemplate
 处理Lob数据
Hibernate为处理特殊数据类型定义了一个接口,org.hibernate.usertype.UserType,Spring有提供这个接口的实现类.可以在Hibernate映射文件中轻松处理LOB类型的数据.
BlobByteArrayType:将BLOB数据映射为byte[]类型的属性.
BlobStringType:将BLOB数据映射为String类型的属性.
BlobSerializable:将BLOB数据映射为Seriablizbel类型的属性.
ClobStringType:将CLOB数据映射为String类型的属性.
指定Type类型后,就可以用HibernateTemplate#save()方法保存了.
 添加Hibernate事件监听器
org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener
 使用原生Hibernate API
如sessionFactory.getCurrentSession().save(forum);sessionFactory.getCurrentSession()获取到当前线程绑定的Session
使用原生的API所抛出的异常是Hibernate异常(也是运行期异常);Dao的调用者只能以普通的错误来处理这些异常.
 使用注解配置(JPA)
基于JPA注解的SessionFactory 通过AnnotionSessionFactoryBean(由Spring提供) 扩展了LocalSessionFactoryBean
 事务处理
 延迟加载的问题
Hibernate允许对关联对象 属性进行延迟加载,但是必须保证延迟加载的操作限于同一个Hibernate Session范围之内进行,如果Service层返回了一个启用了延迟加载功能的
领域对象给Web层,当Web层访问到那些需要延迟加载的数据时,由于领域对象的Hibernate Session已经关闭,这将导致延迟加载数据的访问异常.
Spring专门提供了一个OpenSessionInViewFilter过滤器,它的主要功能是使每个请求过程绑定一个Hibernate Session,即使最初的事务已经完成了,也可以在Web层进行延迟加载的操作.
OpenSessionInViewFilter会造成性能问题,因为每一个WEB请求都会绑定一个Hibernate Session,直到完成请求处理时才会释放数据连接.若不使用的话要调整service接口.
 DAO层设计
 分页查询接口设计
客户端分页:数据一次返回给客户端,在客户端通过展现组件进行数据分页的控制.减小和服务器端交互的次数,提高了系统的交互性.但会增加第一次交互的负荷
数据库分页:数据查询时,数据库仅返回一页的数据.每次切页时都访问数据库,增加了数据库访问的并发性,返回数据小负荷较轻.
服务器端分页:数据查询时,返回全部或多页数据,服务器端处理后返回给客户端仅一页.减少了数据库访问的并发性,同时使服务端返回给客户端的当次负荷也较小,但需要考虑到数据缓存 数据同步等问题,提高了系统复杂性.
    业务层及WEB层技术
  任务调度和异步执行器
Quartz是任务调度领域比较常用的开源框架,Spring提供了集成Quartz的功能.Spring 也为JDK Timer JDK5.0和Executor提供了有益的支持.
 Quartz基础结构
调度器,任务,触发器3个核心的概念
Job:是一个接口,只有一个方法void execute(JobExecutionContext context),实现该接口定义需要执行的任务.
JobDetail:描述Job名称,描述,关联监听器等信息.
Trigger:类,描述触发Job执行的时间触发规则.SimpleTrigger和CronTrigger两个子类.
Calendar:org.quartz.Calendar 一些日历特定时间点的集合.
Scheduler:代表一个Quartz的独立运行容器,Trigger和JobDetail可以注册到Scheduler中,两者在Scheduler中拥有各自的组及名称.可以将Trigger绑定到某一JobDetail中.,线程池为任务提供执行线程.
ThreadPool:Scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率.
CronTrigger 支持日历相关的重复时间间隔(比如每月每一个同一执行),而不是简单的周期时间间隔. Cron表达式时间规则
以下为时间表达式示例:
0 15 10 ? *6#3 每个月的第三个星期五的10:15运行
0 15 10 ? *6L 2007-2009 在2007 2008 2009的每个月的最后一个星期五的10:15运行
在默认情况下Quartz将任务调度的运行信息保存在内存中.
  在Spring中使用Quartz
1)为Quartz的重要组件类提供更具Bean风格的扩展类
2)提供创建Scheduler的BeanFactory类,方便在Spring环境下创建对应的组件对象,并结合Spring容器生命周期进行启动和停止动作.
org.springframework.scheduing.quartz.JobDetailBean 扩展于Quartz的JobDetail
MethodInvokingJobDetailFactoryBean ,可以精确到某个方法作为任务(Job),类不用实现Job接口,但是doJob()方法不能有参数,且不能被持久化到数据库中.
 创建Trigger
SimpleTriggerBean 通过配置文件配置属性
CronTriggerBean 通过配置文件配置属性
 创建Scheduler
SchedulerFactoryBean 通过属性配置文件代替Quartz自身的配置文件.配置与Spring整合Hibernate的形式一样.
 在Spring中使用JDK Timer
java.util.Timer java.util.TimerTask
JDK Timer只适合对执行时间特别短的任务进行调度,因为在Timer中TimerTask都在同一背景线程中执行,长时间的任务会严重影响到Timer的调度工作.
TimerTask实现Runnable接口,可以在run()方法中定义任务逻辑.而Timer负责制定调度规则并调度TimerTask.相当于Quartz中的Job,不同的是:Job每次执行任务都会创建一个Job实例,而JDK Timer则使用相同的实例.
TimerTask是有状态的,对后面的执行是可见的,更像StatefulJob.
 Spring对JDK Timer的支持
1)ScheduledTimerTask 对TimerTask提供封装并提供相关配置
2)MethodInvokingTimerTaskFactoryBean 类可以将一个Bean的方法封装为TimerTask.
3)通过TimerFactoryBean可以更方便的配置Timer,此外让Timer的生命周期和Spring的生命周期息息相关.
 Spring对JDK 5.0的Executor的支持
java.util.concurrent.Executor接口的目的是要将"任务提交"和"任务执行"两者分离
 任务调度对应用程序集群的影响
1)全局任务
2)本地任务
Quartz可支持群集部署,两种方式实现群集,但是无法区分全局任务和本地任务.
1)通过一个中间数据库,使集群节点相互感知,以实现故障切换
2)通过Terracotta进行集群,Terracotta是一个JVM级的开源群集框架,就是将多个JVM透明化成一个JVM使用.
静态变量是ClassLoader级别的,如果WEB应用程序停止,这些静态变量也会从JVM中清除.
但是线程是JVM级别的,如果用户在WEB应用中启动一个线程,这个线程的生命周期并不会和WEB应用程序保持同步,即使停止了WEB应用这个线程依然是活跃的.
如果手工使用JDK Timer,除非手动关闭这个Timer,否则Timer中的任务还会继续执行.
  使用OXM进行对象XML映射
对象XML之间的映射
XML是一组规则和准则的集合,用来描述结构化数据,广泛应用于系统配置,数据存储以及数据交换的格式等.
XML的处理技术
DOM和SAX,
StAX把XML作为一个事件流来处理
 XML处理利器XStream
将Java对象序列化为XML或者将XML反序列化为Java对象
 XStream架构组成
Converters(转换器)
IO(输入/输出)
Context(上下文引用)
Facade(统一入口)
直接调用toXML或fromXML()
使用XSteam别名
 额外功能:处理JSON
JSON,是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成.标准的JavaScript语言的一个子集.
XStream的JettisonMappedXmlDriver和JsonHierarchicalStreamDriver都可以很好的完成Java对象和JSON的相互转换工作.jettison.jar
 其他常见O/X Mapping开源项目
JAXB
编写XML Schema
XML Schema是一个XML的约束文件,定义了XML文件的结构和元素,以及对元素和结构的相关约束.JAXB使用这个Schema文件生成相应的JAVA代码.
XMLBeans 支持XML游标和XQuery
scomp是XMLBeans提供的一个编译工具.
  Castor
是在XML数据,JAVA对象,和数据库关系数据之间提供一种直接的映射.XML与JAVA对象,JAVA对象和数据库关系转换
1)采用XML Schema生成代码方式
2)采用自省方式
3)采用映射文件方式
 JiBX
  Spring OXM
提供了OXM命名空间
Marshaller和Unmarshaller
    Spring MVC
Spring为WEB应用展现层提供了一个优秀的WEB框架-Spring MVC
DispatcherServlet是Spring MVC 的总导演和总策划.它负责截获请求并将其分派给相应的处理器处理.Spring MVC框架包括注解驱动控制器,请求及响应的信息处理,视图解析,本地化解析,上传文件解析,异常处理以及表单标签绑定等内容.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值