Spring2.5.6及Spring3.0.5所有jar下载地址
spring jar包 官方下载地址 文档下载地址。2.56版本 和3.05版本
http://s3.amazonaws.com/dist.springframework.org/release/SPR/spring-framework-2.5.6-with-docs.zip
spring 的核心机制:依赖注入
当某个java实例需要调用另一个java实例,传统情况下是由调用者来创建的,一般是用new来创建。
而依赖注入模式下,实例不需要调用者来创建,而是由spring来完成(即所谓的控制反转),然后注入调用者。
依赖注入的方式:
比较常用的有两种方式1 设置注入即Ioc容器的属性setter的方式注入被依赖实例<property name="" ref="">
2构造注入即Ioc容器使用构造器注入被依赖实例<constructor-arg ref=""> index指定构造参数作为第几个构造参数值
spring 容器是生成bean实例的工厂,并管理spring的bean是spring的基本单元所有的组件都被当成bean来处理包括 数据源,事务管理,hibernate的sessionFactory.
bean后处理器是一种特殊的Bean它并不对外提供服务甚至可以没有id/属性。它主要负责对容器中的其他Bean执行后期处理。后处理器必须实现BeanPostProcessor接口。此接口有两个方法:Object postProcessorBeforeInitalization(Object object,String name) ,Object postProcessorAfterInitalization(Object object,String name)
第一个参数是系统即将后处理的Bean实例,第二个参数是该Bean实例的名称。
如果使用BeanFactory作为spring容器则必须手动注册容器后处理器。
类似于Bean后处理器,采用ApplicationContext作为容器,则无需手动注册容器后处理器。即所谓的spring“零配置”的支持也就是
Spring注解
1,搜索Bean类
spring提供如下几个Annotarion来标注Spring
@Component 来标注一个普通的spring Bean;
@Controller 来标注一个控制器组件类;
@Srevice来标注一个业务逻辑组件类;
@Repsitory:标注一个Dao组件;
<context:component-scan base-packge=" "/> 默认,自动搜索所有以上注释存在的java类,当做Spring Bean处理。还可以通过<context:componet-scan base-package=" "/>子元素<include-fileter>/<exclude-filter>
2.指定Bean的作用域
@Scope("portotype")
3.使用@Resource装配
默认情况下@Resource有一个name属性,Spring将这个值 解释为需要被注入的Bean的实例的名字,换句话说,使用@Resource与<property../>元素的ref具有相同的结果。
当使用@Resource 修饰File时如果不写name则默认与File相同。
4.自动装配和精装配
@Autowried指定自动装配,使用@Autowired可以标志setter,方法,普通方法,和构造器。如:
@Component
public class Chiness implements Person{
@Autowired
private Province province;
@Autowired
public Chinese(Provice province){
this.province=province;
}
@Autowired
private Province[] provinces;
}
当@Autowied标注File时Spring 会把容器中的与该Filed类型匹配的Bean注入到该属性,
如果Spring容器中包含多个相同类型的Bean与Filed类型匹配,则会出现异常。
当@Autowied标注数组类时,在这种情况,Spring会自动搜索Spring容器中所有与数组类型相匹配的的类型Bean,并把这些Bean当作数组元素来创建数组。
当@Autowied标注集合时,和标注数组类似,但是必须用泛型。
5.使用@Qualifier精确装配
@Autowied 总是使用byType的自动装配策略,这种情况下,符合自动装配的类型Bean常常有多个这个时候就会引发异常,为了实现能精确的配置,Spring提供了@Qualifier,可以根据Bean标识来指定自动装配,@Qualifier可以标注Fileld,如:
@Component
public class Chiness implements Person{
@Autowired
@Qualifier("protName")
private Province province;
}
@Qualifier还可以标注方法的参数,如:
@component
public class Chiness implements Person{
@Autowired
private Province province;
public void setProvince(@Qualifier("proName") Province province){
this.province=province;
}
}
Spring 的AOp
aop 基本概念
切面(Aspect):业务流程运行到某个特定的步骤,也就是一个应用运行的关注点,关注点可能横切多个对象,所以产出被称为横切关注点。
连接点(Joinpoint):程序执行过程明确的点,如方法的调用、异常的抛出,SpringAop中连接点总是方法的调用。
增强处理(Advice):AOP框架在特定的切入点执行的增强处理有 around,before 和after等类型。
切入点(Pointcut):可以插入增强处理点的连接点,简而言之,当某个连接点满足指定要求时,连接点将被添加增强处理,改连接点也就变成了切入点。
例如:
pointcut xxxPointcut(){
:execution(void H*.say*);
}
每个方法的调用都只是连接点,但如果该方法属于H开头的类并且方法名以say开头,按照方法执行将变为切入点。
引入:将方法添加到被处理的类中,Spring允许引入新的接口到任何被处理的对象。例如:你可以使用一个引用,是任何对象实现IsModified接口,以此简化缓存。
目标对象:被Aop增强处理的对象也被称为增强的对象,如果AOP框架是通过运行时代理来实现的,那么这个对象僵尸一个被代理的对象。
AOP代理;AOP框架创建的对象,简单的说,代理就是对目标对象的加强,Spring 的AOP代理可以使用JDK动态代理,也可以是CGLIB代理,前者为实现接口的目标对象的 代 理后者为不实现接口的目标对象代理。
织入(Weaving):将增强处理加到目标对象中,并创建一个呗增强的对象(AOP代理)的过程就是织入。织入有两种方式实现:编译时增强(如AspectJ)和运行时增强(如CGLIB)
目前Spring 只支持将方法调用作为连接点,如果需要把Fileld的访问和更新也作为增强处理的链接点,可以使用AspectJ.
一旦我们掌握了上面关于AOP相关的概念,不难发现AOP的编程实际上只需要程序员参与3个部分:
定义普通业务组件;
定义切入点,一个切入点横切多个业务组件;
定义增强处理,增强处理就是现在AOP框架为普通业务组件织入的处理动作。
AOP,基于Annotation的零配置方式;
定义Before增强处理:
当我们在一个切面类里使用@Before来标注一个方法时,该方法将作为Before增强处理,使用@Before标注时通常要指定一个value属性值,用来指定该增强处理器将被织入哪些切入点。
("execution(* com.aplaction.spring.*.*(..))") 第一个星号后面一定要有一个空格
//定义一个切面
@Aspect
public class BeforeAdviceTest{
//执行com.aplaction.spring包下所有方法都作为切入点
@Before("execution(* com.aplaction.spring.*.*(..))")
public void authority(){
System.out.println("--------------");
}
}
@Aspect标注BeforeAdviceTest 表明该类是一个切面类,在该切面里定义了一个authority()方法,这个方法本来没上面特别之处,但是因为使用了@Befor标注,该方法变成了一个增强处理。这里@Before指定了com.aplaction.spring下所有方法都作为切入点。
Spring 事务管理
Spring 声明式事务让我们从复杂的事务处理中得到解脱。使得我们再也无需去处理获得链接、关闭链接、事务提交和回滚等操作。再也不用再与事务相关的方法中大量的使用try...catch...finally代码。
事务属性通常是由事务的传播行为,事务的隔离级别,事务的超时值和事务的只读标志组成。我们在进行事务划分时,需要定义,也就是要配置事务的属性。
Spring 在TransactionDefinition 接口中定义了这些属性,以供PlatfromTransactionManager使用,PlatfromTransactionManager是Spring事务管理的核心接口。
TransactionDefintion
public interface TransactionDefintion{
int getPropagationBehavior();//返回事务的传播行为,由是否有一个活动的事务来决定一个事务调用。
int getIsolationLevel();//事务隔离级别,事务管理器根据它来控制另外一个事务可以看到本事务内的哪些数据。
int getTimeout();//事务必须在多少秒钟内完成
boolean isReadOnly();//事务是否只读
}
事务的隔离级别:
ISOLATION_DEFAULT这是一个platfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别,另外四个与JDBC的隔离级别相对应,ISOLATION_READ_UNCOMMITTED这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
ISOLATION_READ_COMMITTED保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事物未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了不可重复读的情况产生。
ISOLATION_REPEATABLE_READ可以避免脏读,不可重复读但是会出现幻像读。
ISOLATION_SERIALIZABLE可以避免脏读,不可重复读和幻像读。(这是花费代价最高的事务隔离级别,事务处理为顺序执行)
事务的传播行为:
PROPAGATION_REQUIRED 如果存在一个事务,则支持当前事务。如果没有事务,则开启一个新的事务。
PROPAGATION_SUPPORTS如果存在一个事务,则支持当前事务。如果没有事务,则非事务的执行。
PROPAGATION_MANDATORY 如果已经存在一个事务,支持当前事务。如果没有则抛出异常。
PROPAGATION_REQUIRES_NEW: 总是开启一个新的事务。如果一个事务已经存在,则将该事务挂起。(新的事务执行完再执行挂起的事务)
PROPAGATION_NOT_SUPPORTED:总是非事务地执行,并挂起任何存在的事务。
PROPAGATION_NESTED:如果一个活动的事务存在,则运行一个嵌套的事务中,如果没有活动事务,则按TransactionDefinition.PROPAGATION_REQUIRED属性执行。
PROPAGATION_NESTED:与PROPAGATION_REQUIRES_NEW类似,都像是一个嵌套事务,如果不存在一个活动的事务,都会开启一个新的事务。使用 PROPAGATION_REQUIRES_NEW时,内存事务与外层事务是两个独立的事务,一旦内层事务提交后,外层事务不能对其进行回滚。两个事务互不影响。而使用 PROPAGATION_NESTED时,外层事务的回滚可以引起内层事务的回滚。而内层事务的异常并不会导致外层事务的回滚,它是一个真正的嵌套事务。DataSourceTranscationManager使用savepoint支持PROPAGATION_NESTED时,需要JDBC3.0以上驱动及1.4以上的JDK版本支持。
这三个需要使用JtaTransactionManager作为事务管理器
PROPAGATION_NEVER:总是非事务的执行,如果存在一个活动的事务,则抛出异常
PROPAGATION_REQUIRED 一般情况下是我们首选的事务传播行为。也就是如果存在一个事务,则支持当前事务。如果没有事务,则开启一个新的事务。它能满足我们大多数需求。
那么在spring管理的项目中如何知道一个事务什么时候以及在哪儿做的回滚操作的呢?
答案自然是在进行增删改查操作的时候来控制的。
好了又有问题了,你有没有遇到过这样的情况?事务执行中系统抛出了异常,但是但是事务却没回滚。
Spring 缺省对java运行时异常和未检查异常回滚的,其他类型并不回滚。所以有必要对配置做一些修改抛出异常的时候就回滚,方便处理
先定义父类
<bean id="baseTxService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
<property name="transactionManager" ref="transactionManager" />
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="save*">PROPAGATION_REQUIRED,-Exception</prop> //这里-Exception表示所有异常都回滚
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
再定义子类让它继承父类
<bean id="magazineManager" parent="baseTxService">
<property name="target">
<bean class="com.harmony.magazine.service.impl.MagazineManager">
<property name="magazineDao">
<ref bean="magazineDao" />
</property>
</bean>
</property>
</bean>