然后我们要改一下代理对象DynaProxyHello中的代码.如下:1packagesinosoft.dj.aop.proxyaop;
2
3importjava.lang.reflect.InvocationHandler;
4importjava.lang.reflect.Method;
5importjava.lang.reflect.Proxy;
6
7publicclassDynaProxyHelloimplementsInvocationHandler{
8 /**
9 * 操作者
10 */
11 privateObject proxy;
12 /**
13 * 要处理的对象(也就是我们要在方法的前后加上业务逻辑的对象,如例子中的Hello)
14 */
15 privateObject delegate;
16
17/**
18 * 动态生成方法被处理过后的对象 (写法固定)
19 *
20 *@paramdelegate
21 *@paramproxy
22 *@return
23 */
24 publicObject bind(Object delegate,Object proxy){
25
26 this.proxy=proxy;
27 this.delegate=delegate;
28 returnProxy.newProxyInstance(
29 this.delegate.getClass().getClassLoader(),this.delegate
30 .getClass().getInterfaces(),this);
31 }
32 /**
33 * 要处理的对象中的每个方法会被此方法送去JVM调用,也就是说,要处理的对象的方法只能通过此方法调用
34 * 此方法是动态的,不是手动调用的
35 */
36 publicObject invoke(Object proxy, Method method, Object[] args)
37 throwsThrowable{
38 Object result=null;
39 try{
40 //反射得到操作者的实例
41 Class clazz=this.proxy.getClass();
42 //反射得到操作者的Start方法
43 Method start=clazz.getDeclaredMethod("start",
44 newClass[]{ Method.class});
45 //反射执行start方法
46 start.invoke(this.proxy,newObject[]{ method });
47 //执行要处理对象的原本方法
48 result=method.invoke(this.delegate, args);
49// 反射得到操作者的end方法
50 Method end=clazz.getDeclaredMethod("end",
51 newClass[]{ Method.class});
52// 反射执行end方法
53 end.invoke(this.proxy,newObject[]{ method });
54
55 }catch(Exception e){
56 e.printStackTrace();
57 }
58 returnresult;
59 }
60
61}
62 然后我们把Test.java中的代码改一下.测试一下:packagesinosoft.dj.aop.proxyaop;
publicclassTest{
publicstaticvoidmain(String[] args){
IHello hello=(IHello)newDynaProxyHello().bind(newHello(),newLoggerOperation());
hello.sayGoogBye("Double J");
hello.sayHello("Double J");
}
}
结果还是一样的吧.如果你想在每个方法之前加上日志记录,而不在方法后加上日志记录.你就把LoggerOperation类改成如下:1packagesinosoft.dj.aop.proxyaop;
2
3importjava.lang.reflect.Method;
4
5publicclassLoggerOperationimplementsIOperation{
6
7 publicvoidend(Method method){
8 //Logger.logging(Level.DEBUGE, method.getName() + " Method end.");
9 }
10
11 publicvoidstart(Method method){
12 Logger.logging(Level.INFO, method.getName()+"Method Start!");
13 }
14
15}
16 运行一下.你就会发现,每个方法之后没有记录日志了. 这样,我们就把代理者和操作者解藕了!下面留一个问题给大家,如果我们不想让所有方法都被日志记录,我们应该怎么去解藕呢.?我的想法是在代理对象的public Object invoke(Object proxy, Method method, Object[] args)方法里面加上个if(),对传进来的method的名字进行判断,判断的条件存在XML里面.这样我们就可以配置文件时行解藕了.如果有兴趣的朋友可以把操作者,被代理者,都通过配置文件进行配置 ,那么就可以写一个简单的SpringAOP框架了.
posted @
2009-07-24 20:43 jadmin 阅读(93) |
评论 (0) |
编辑 收藏
从上面的例子我们看出.只要你是采用面向接口编程,那么,你的任何对象的方法执行之前要加上记录日志的操作都是可以的.他(DynaPoxyHello)自动去代理执行被代理对象(Hello)中的每一个方法,一个java.lang.reflect.InvocationHandler接口就把我们的代理对象和被代理对象解藕了.但是,我们又发现还有一个问题,这个DynaPoxyHello对象只能跟我们去在方法前后加上日志记录的操作.我们能不能把DynaPoxyHello对象和日志操作对象(Logger)解藕呢?结果是肯定的.让我们来分析一下我们的需求.我们要在被代理对象的方法前面或者后面去加上日志操作代码(或者是其它操作的代码),那么,我们可以抽象出一个接口,这个接口里就只有两个方法,一个是在被代理对象要执行方法之前执行的方法,我们取名为start,第二个方法就是在被代理对象执行方法之后执行的方法,我们取名为end .接口定义如下 :1packagesinosoft.dj.aop.proxyaop;
2
3importjava.lang.reflect.Method;
4
5publicinterfaceIOperation{
6 /**
7 * 方法执行之前的操作
8 *@parammethod
9 */
10 voidstart(Method method);
11 /**
12 * 方法执行之后的操作
13 *@parammethod
14 */
15 voidend(Method method);
16}
17 我们去写一个实现上面接口的类.我们把作他真正的操作者,如下面是日志操作者的一个类:LoggerOperation.javapackagesinosoft.dj.aop.proxyaop;
importjava.lang.reflect.Method;
publicclassLoggerOperationimplementsIOperation{
publicvoidend(Method method){
Logger.logging(Level.DEBUGE, method.getName()+"Method end.");
}
publicvoidstart(Method method){
Logger.logging(Level.INFO, method.getName()+"Method Start!");
}
}
posted @
2009-07-24 20:42 jadmin 阅读(68) |
评论 (0) |
编辑 收藏
但是我们会发现一个问题,如果我们像Hello这样的类很多,那么,我们是不是要去写很多个HelloProxy这样的类呢.没错,是的.其实也是一种很麻烦的事.在jdk1.3以后.jdk跟我们提供了一个API java.lang.reflect.InvocationHandler的类. 这个类可以让我们在JVM调用某个类的方法时动态的为些方法做些什么事.让我们把以上的代码改一下来看看效果.
同样,我们写一个IHello的接口和一个Hello的实现类.在接口中.我们定义两个方法;代码如下 :
IHello.java
1package sinosoft.dj.aop.proxyaop;
2
3public interface IHello {
4 /**
5 * 业务处理A方法
6 * @param name
7 */
8 void sayHello(String name);
9 /**
10 * 业务处理B方法
11 * @param name
12 */
13 void sayGoogBye(String name);
14}
15
Hello.java
1package sinosoft.dj.aop.proxyaop;
2
3public class Hello implements IHello {
4
5 public void sayHello(String name) {
6 System.out.println("Hello " + name);
7 }
8 public void sayGoogBye(String name) {
9 System.out.println(name+" GoodBye!");
10 }
11}
12
我们一样的去写一个代理类.只不过.让这个类去实现java.lang.reflect.InvocationHandler接口,代码如下:
1package sinosoft.dj.aop.proxyaop;
2
3import java.lang.reflect.InvocationHandler;
4import java.lang.reflect.Method;
5import java.lang.reflect.Proxy;
6
7public class DynaProxyHello implements InvocationHandler {
8
9 /**
10 * 要处理的对象(也就是我们要在方法的前后加上业务逻辑的对象,如例子中的Hello)
11 */
12 private Object delegate;
13
14/**
15 * 动态生成方法被处理过后的对象 (写法固定)
16 *
17 * @param delegate
18 * @param proxy
19 * @return
20 */
21 public Object bind(Object delegate) {
22 this.delegate = delegate;
23 return Proxy.newProxyInstance(
24 this.delegate.getClass().getClassLoader(), this.delegate
25 .getClass().getInterfaces(), this);
26 }
27 /**
28 * 要处理的对象中的每个方法会被此方法送去JVM调用,也就是说,要处理的对象的方法只能通过此方法调用
29 * 此方法是动态的,不是手动调用的
30 */
31 public Object invoke(Object proxy, Method method, Object[] args)
32 throws Throwable {
33 Object result = null;
34 try {
35 //执行原来的方法之前记录日志
36 Logger.logging(Level.DEBUGE, method.getName() + " Method end .");
37
38 //JVM通过这条语句执行原来的方法(反射机制)
39 result = method.invoke(this.delegate, args);
40 //执行原来的方法之后记录日志
41 Logger.logging(Level.INFO, method.getName() + " Method Start!");
42 } catch (Exception e) {
43 e.printStackTrace();
44 }
45 //返回方法返回值给调用者
46 return result;
47 }
48
49}
50
上面类中出现的Logger类和Level枚举还是和上一上例子的实现是一样的.这里就不贴出代码了.
让我们写一个Test类去测试一下.代码如下:
Test.java
1package sinosoft.dj.aop.proxyaop;
2
3public class Test {
4 public static void main(String[] args) {
5 IHello hello = (IHello)new DynaProxyHello().bind(new Hello());
6 hello.sayGoogBye("Double J");
7 hello.sayHello("Double J");
8
9 }
10}
11
运行输出的结果如下:
Tue Mar 04 21:24:03 CST 2008 sayGoogBye Method end .
Double J GoodBye!
2008-3-4 21:24:03 sayGoogBye Method Start!
Tue Mar 04 21:24:03 CST 2008 sayHello Method end .
Hello Double J
2008-3-4 21:24:03 sayHello Method Start!
由于线程的关系,第二个方法的开始出现在第一个方法的结束之前.这不是我们所关注的!
posted @
2009-07-24 20:40 jadmin 阅读(82) |
评论 (0) |
编辑 收藏
好长时间没有用过Spring了. 突然拿起书.我都发现自己对AOP都不熟悉了.其实AOP的意思就是面向切面编程.OO注重的是我们解决问题的方法(封装成Method),而AOP注重的是许多解决解决问题的方法中的共同点,是对OO思想的一种补充!还是拿人家经常举的一个例子讲解一下吧:比如说,我们现在要开发的一个应用里面有很多的业务方法,但是,我们现在要对这个方法的执行做全面监控,或部分监控.也许我们就会在要一些方法前去加上一条日志记录,我们写个例子看看我们最简单的解决方案我们先写一个接口IHello.java代码如下:1packagesinosoft.dj.aop.staticaop;
2
3publicinterfaceIHello{
4 /**
5 * 假设这是一个业务方法
6 *@paramname
7 */
8 voidsayHello(String name);
9}
10 里面有个方法,用于输入"Hello" 加传进来的姓名;我们去写个类实现IHello接口packagesinosoft.dj.aop.staticaop;
publicclassHelloimplementsIHello{
publicvoidsayHello(String name){
System.out.println("Hello"+name);
}
}
现在我们要为这个业务方法加上日志记录的业务,我们在不改变原代码的情况下,我们会去怎么做呢?也许,你会去写一个类去实现IHello接口,并依赖Hello这个类.代码如下:1packagesinosoft.dj.aop.staticaop;
2
3publicclassHelloProxyimplementsIHello{
4 privateIHello hello;
5
6 publicHelloProxy(IHello hello){
7 this.hello=hello;
8 }
9
10 publicvoidsayHello(String name){
11 Logger.logging(Level.DEBUGE,"sayHello method start.");
12 hello.sayHello(name);
13 Logger.logging(Level.INFO,"sayHello method end!");
14
15 }
16
17}
18 其中.Logger类和Level枚举代码如下:Logger.java1packagesinosoft.dj.aop.staticaop;
2
3importjava.util.Date;
4
5publicclassLogger{
6 /**
7 * 根据等级记录日志
8 *@paramlevel
9 *@paramcontext
10 */
11 publicstaticvoidlogging(Level level, String context){
12 if(level.equals(Level.INFO)){
13 System.out.println(newDate().toLocaleString()+""+context);
14 }
15 if(level.equals(Level.DEBUGE)){
16 System.err.println(newDate()+""+context);
17 }
18 }
19
20}
21 Level.java1packagesinosoft.dj.aop.staticaop;
2
3publicenumLevel{
4 INFO,DEBUGE;
5}
6 那我们去写个测试类看看,代码如下:Test.java1packagesinosoft.dj.aop.staticaop;
2
3publicclassTest{
4 publicstaticvoidmain(String[] args){
5 IHello hello=newHelloProxy(newHello());
6 hello.sayHello("Doublej");
7 }
8}
9 运行以上代码我们可以得到下面结果:Tue Mar0420:57:12CST2008sayHello method start.
Hello Doublej
2008-3-420:57:12sayHello method end! 从上面的代码我们可以看出,hello对象是被HelloProxy这个所谓的代理态所创建的.这样,如果我们以后要把日志记录的功能去掉.那我们只要把得到hello对象的代码改成以下:1packagesinosoft.dj.aop.staticaop;
2
3publicclassTest{
4 publicstaticvoidmain(String[] args){
5 IHello hello=newHello();
6 hello.sayHello("Doublej");
7 }
8}
9 上面代码,可以说是AOP最简单的实现!
posted @
2009-07-24 20:37 jadmin 阅读(70) |
评论 (0) |
编辑 收藏
<SCRIPT LANGUAGE="JavaScript">
function selectInst(){
var checkbox = document.getElementsByName("inst");
for(i=0;i<checkbox.length;i++){
if(checkbox[i].checked){
var temp = checkbox[i].value;
alert(temp);
}
}
}
</SCRIPT>
<form>
选择爱好:<br>
<input type="checkbox" name="inst" value="足球">足球
<input type="checkbox" name="inst" value="篮球">篮球
<input type="checkbox" name="inst" value="音乐">音乐
<input type="checkbox" name="inst" value="上网">上网
<input type="checkbox" name="inst" value="跳舞">跳舞
<input type="button" value="提交" onclick="selectInst()">
</form>
posted @
2009-07-20 22:30 jadmin 阅读(78) |
评论 (0) |
编辑 收藏
<SCRIPT LANGUAGE="JavaScript">
var checkFlag = "false";
function selectAll(field){
if(checkFlag=="false"){
for(i=0;i<field.length;i++){
field[i].checked=true;
}
checkFlag = "true";
}else{
for(i=0;i<field.length;i++){
field[i].checked=false;
}
checkFlag = "false";
}}
</SCRIPT>
<form>
选择爱好: <br>
<input type="checkbox" name="inst" value="足球">足球
<input type="checkbox" name="inst" value="篮球">篮球
<input type="checkbox" name="inst" value="音乐">音乐
<input type="checkbox" name="inst" value="上网">上网
<input type="checkbox" name="inst" value="跳舞">跳舞
<input type="checkbox" name="chkAll" value="instAll" onclick="selectAll(this.form.inst)">全选<br>
</form>
posted @
2009-07-20 22:28 jadmin 阅读(121) |
评论 (0) |
编辑 收藏
一、AOP 概念
Joinpoint:它定义在哪里加入你的逻辑功能,对于Spring AOP,Jointpoint指的就是Method。
Advice:特定的Jointpoint处运行的代码,对于Spring AOP 来讲,有Before advice、AfterreturningAdvice、ThrowAdvice、AroundAdvice(MethodInteceptor)等。
Pointcut:一组Joinpoint,就是说一个Advice可能在多个地方织入,
Aspect:这个我一直迷惑,它实际是Advice和Pointcut的组合,但是Spring AOP 中的Advisor也是这样一个东西,但是Spring中为什么叫Advisor而不叫做Aspect。
Weaving:将Aspect加入到程序代码的过程,对于Spring AOP,由ProxyFactory或者ProxyFactoryBean负责织入动作。
Target:这个很容易理解,就是需要Aspect功能的对象。
Introduction:引入,就是向对象中加入新的属性或方法,一般是一个实例一个引用对象。当然如果不引入属性或者引入的属性做了线程安全性处理或者只读属性,则一个Class一个引用也是可以的(自己理解)。Per-class lifecycle or per-instance life cycle
二、AOP 种类
1、静态织入:指在编译时期就织入Aspect代码,AspectJ好像是这样做的。
2、动态织入:在运行时期织入,Spring AOP属于动态织入,动态织入又分静动两种,静则指织入过程只在第一次调用时执行;动则指根据代码动态运行的中间状态来决定如何操作,每次调用Target的时候都执行(性能较差)。
三、Spring AOP 代理原理
Spring AOP 是使用代理来完成的,Spring 会使用下面两种方式的其中一种来创建代理:
1、JDK动态代理,特点只能代理接口,性能相对较差,需要设定一组代理接口。
2、CGLIB 代理,可代理接口和类(final method除外),性能较高(生成字节码)。
四、Spring AOP 通知类型
1、BeforeAdvice:前置通知需实现MethodBeforeAdvice,但是该接口的Parent是BeforeAdvice,致于什么用处我想可能是扩展性需求的设计吧。或者Spring未来也并不局限于Method的JoinPoint(胡乱猜测)。BeforeAdvice可以修改目标的参数,也可以通过抛出异常来阻止目标运行。
2、AfterreturningAdvice:实现AfterreturningAdvice,我们无法修改方法的返回值,但是可以通过抛出异常阻止方法运行。
3、AroundAdvice:Spring 通过实现MethodInterceptor(aopalliance)来实现包围通知,最大特点是可以修改返回值,当然它在方法前后都加入了自己的逻辑代码,因此功能异常强大。通过MethodInvocation.proceed()来调用目标方法(甚至可以不调用)。
4、ThrowsAdvice:通过实现若干afterThrowing()来实现。
5、IntroductionInterceptor:Spring 的默认实现为DelegatingIntroductionInterceptor
五、Spring AOP Pointcut
以上只是Advice,如果不指定切入点,Spring 则使用所有可能的Jointpoint进行织入(当然如果你在Advice中进行方法检查除外)。因此切入点在AOP中扮演一个十分重要的角色。Spring 2.0 推荐使用AspectJ的Annocation的切入点表达式来定义切入点,或者使用<aop:xxx/>来定义AOP,这方面本篇不做考虑。
1、Pointcut:它是Spring AOP Pointcut的核心,定义了getClassFilter()和getMethodMatcher()两个方法。
2、ClassFilter:定义了matches(Class cls)一个方法。
3、MethodMatcher() 定义了matches(Method,Class),isRuntime(),matches(Mathod,Class,Object[])三个方法,如果isRuntime()返回true则表示为动态代理(实际是动态代理的动态代理),则调用第三个方法(每访问一次调用一次),否则调用第一个方法(并且只调用一次)
4、Spring AOP 静态切入点的几个实现。
ComposablePointcut 太复杂一个切入点无法表达就用这个,union MethodMatcher和ClassFilter或者intersection MethodMatcher、ClassFilter和Pointcut。为什么不实现union Pointcut? 而只能通过Pointcuts类对Pointcut进行union操作。
ControlFlowPointcut 想对程序的运行过程进行追踪就用这个
DynamicMatchMatcherPointcut 想用动态AOP 就用这个
JdkRegexpMethodPointcut 想使用正则表达式就用这个
Perl5RegexpMethodPointcut
NameMatchMethodPointcut 想用方法名字来匹配就用这个
StaticMethodMatcherPointcut 静态切入点就用这个
没有人反对你直接实现Pointcut:)。
六、Spring AOP 中的Advisor其实就是Aspect
1、 PointcutAdvisor
其实一般使用DefaultPointcutAdvisor就足够了,给它Advice和Pointcut。
当然如果想少写那么几行代码也可以使用NameMatchMethodPointcutAdvisor,RegexpMethodPointcutAdvisor等。
更多Advisor可以查看API文档。
2、 IntroductionAdvisor
默认实现为DefaultIntroductionAdvisor。
七、AOP ProxyFactory
使用代码实现AOP 可使用ProxyFactory
声明式AOP 可使用ProxyFactoryBean
ProxyFactoryBean 需要设定 target,interceptorNames(可以是Advice或者Advisor,注意顺序)
对接口代理需设置proxyInterfaces
八、自动代理
BeanNameAutoProxyCreator
- <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
- <property name="beanNames"><value>jdk*,onlyJdk</value></property>
- <property name="interceptorNames">
- <list>
- <value>myInterceptor</value>
- </list>
- </property>
- </bean>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames"><value>jdk*,onlyJdk</value></property>
<property name="interceptorNames">
<list>
<value>myInterceptor</value>
</list>
</property>
</bean>
DefaultAdvisorAutoProxyCreator
- <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
- <bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
- <property name="transactionInterceptor" ref="transactionInterceptor"/>
- </bean>
- <bean id="customAdvisor" class="com.mycompany.MyAdvisor"/>
- <bean id="businessObject1" class="com.mycompany.BusinessObject1">
- <!-- Properties omitted -->
- </bean>
- <bean id="businessObject2" class="com.mycompany.BusinessObject2"/>
posted @
2009-07-20 21:44 jadmin 阅读(146) |
评论 (0) |
编辑 收藏
需明确的几个概念:
l 通知(Advice):用于告知系统将有哪些新的行为。
l 切入点(Pointcut):定义了通知应该在应用到那些连接点。
l 目标对象(Target):被通知的对象。
l 代理(Proxy):将通知应用到目标对象后创建的对象。
Spring有两种代理创建方式:
1. 如果目标对象实现了一个或多个接口暴露的方法,Spring将使用JDK的java.lang.reflect.Proxy创建代理。这个类让Spring动态产生一个新的类,它实现了所需的接口,织入了通知,并且代理目标的所有请求。(这篇主要介绍这个方式)
2. 如果目标对象没有实现任何接口,Spring使用CGLIB库生成目标对象的子类。在创建这个子类的时候,Spring将通知织入,并且将对目标对象的调用委托给这个子类。
下面以一个实例说明Spring AOP的基本开发方法:
一.创建通知
Spring连接点模型是建立在方法拦截上,这意味着你编写的
Spring通知会在方法调用周围的各个地方织入系统中。
TestAopServiceAdvice实现了接口MethodBeforeAdvice(前置通知),并实现它的惟一的方法before,这个类就可以在调用目标对象前被调用。同样的还有AfterReturningAdvice(后置通知),MethodInterceptor(环绕通知),异常通知(ThrowsAdvice),引入通知等。
在这个方法中我们输出了一个字符串TestAopServiceAdvice,用于验证这个方法是否在目标对象前调用了。
注意:我们无法改变before方法中的参数args和target中的值,args中存的是原来要传入目标对象的变量,target即指目标对象。
二.配置Spring XML配置文件
要在Spring中实现AOP,一般情况下需要配置4个bean:
1. 目标对象(target)
2. 通知(advice)
3. 切入点(pointcut)
4. 代理(proxy)
切入点又分为静态切入点和动态切入点
l 静态切入点的意思是通知总是被执行,也是最常用的一种切入点。
l 动态切入点根据运行时方法的参数值决定通知是否被执行。
在图2中,定义了使用了一个Spring提供的静态切入点
NameMatchMethodPointAdvisor,它保证了当被调用的方法的名字与给出的映射名字相匹配的时候,这个切入点才匹配。
Spring提供的另一个静态切入点为RegexpMethodPointcutAdvisor,让你可以利用正则表达式来定义切入点,正则表达式需要jakarta-oro.jar包的支持。
使用ProxyBeanFactory可以创建一个被通知的类,即代理对象。它的最常用的三个控制行为的属性是:
l proxyInterfaces:代理应该实现的接口列表。
l interceptorNames:需要应用到目标对象上的通知Bean的名字。可以是拦截器、Advisor或其他通知类的名字。
注:在用容器的getBean方法时,应该是getBean(代理类的名字),而不是getBean(目标对象的名字),否则AOP无法工作。
posted @
2009-07-20 21:43 jadmin 阅读(81) |
评论 (0) |
编辑 收藏
Spring2.5是Spring2.1各个里程碑版本的终结。
Spring2.5是对Spring2.0的增强,增加了一些新的特性:
- 全面支持java6和javaEE5(JDBC 4.0, JTA 1.1, JavaMail 1.4, JAX-WS 2.0等)
- 全特性的注释驱动依赖注入,包括对限定词的支持
- 支持基于classpath的组件扫描,自动侦测有注释的类
- 支持AspectJ切点表达式中包含bean name切点元素
- 内置AspectJ加载时编织,基于LoadTimeWeaver 提取
- 更多的XML配置文件的名字空间支持,比如context和jms等,最大程度提高编写的方便性
- 全面修订集成测试框架,支持JUnit4和TestNG
- 新的基于注释的Servlet MVC和Portlet MVC控制器风格配置
- 扩展SimpleJdbcTemplate功能,支持命名的参数等
- 官方认可的Websphere支持,支持WebSphere 6 UOWManager 机制
- Spring框架的jar文件,兼容OSGi绑定,并能直接使用
- Spring ApplicationContext可被部署为JCA RAR文件,用于非主导应用模块
- JCA 1.5消息终端管理,用于Spring管理的JMS和CCI消息监听器
另外,分发包有三种形式,增加了最小标准zip包和包含文档的zip包。
官方推荐升级所有2.0.x版本到2.5版本,因为可以从新特性中获益和显著提升性能。
Spring2.0可以简单的升级到2.5版本,只需替换相关jar文件。
Spring2.5仍然兼容JDK1.4.2+和J2EE1.3+。
posted @
2009-07-20 01:45 jadmin 阅读(74) |
评论 (0) |
编辑 收藏
一、事务管理
事务传播
1、required:方法在一个事务中执行,如果调用的方法在一个事务中,则使用该事务,否则将创建一个新的事务。(必须有,有就用,没有就建)
2、mandatory:如果运行于事务中的客户调用了该方法,方法在客户的事务中执行。如果客户没有关联到事务中,容器就会抛出TransactionRequiredException.(必须有,有就用,没有报错)
3、requiresnew:方法将在一个新的事务中执行,如果调用的方法已经在一个事务中,则暂停旧的事务。在调用结束后恢复旧的事务。(必须有,有没有都要建)
4、supports:如果方法在一个事务中被调用,则使用该事务,否则不使用事务。(有没有都中,有就用,没有不用)
5、not_supported:如果方法在一个事务中被调用,容器会在调用之前终止该事务。在调用结束后,容器会恢复客户事务。如果客户没有关联到一个事务中,容器不会入运行在该方法启动一个新的事务。用notsupported属性标识不需要事务的方法。因为事务会带来更高的性能支出,所以这个属性可以提高性能。(不需要,有就挂起事务,没有直接运行)
6、Never:如果在一个事务中调用该方法,容器会抛出RemoteException。如果客户没有关联到一个事务中,容器不会在运行入该方法前启动一个新的事务。(必须没有,有就报错,没有就直接运行)
事务隔离
为什么要使用事物隔离,是因为事物并发引起的一些错误现象
并发问题:
脏读:一个事务读取了未提交的事务
不可重复读:同一个事务中多次读取同一个数据返回的结果不同
幻读:一个事务读取到了另一个事务已提交的insert数据。
事务并发处理:
共享锁:共享锁用于读取数据操作,它允许其他事务同时读取某锁定的资源,但不允许其他事务更新它。
排他锁:排它锁用于修改数据的场合。它锁定的资源,其他事务不能读取也不能修改。
更新锁:更新锁在更新操作的初始化阶段用来锁定可能要被修改的资源,从而避免使用共享锁造成的死锁现象。
事务隔离级别:
ReadUncommitted:读未提交数据,该选项指示数据库读取数据时不使用任何锁。在这种情况下,事务可以读取到未提交的数据,会出现脏读,不可重复读和幻读现象。
ReadCommited:
该选项只会返回"读取时间点"之前已提交的数据。因此可以避免脏读,但是会出现不可重复读,另外还会出现幻读现象。
RepeatableRead:该选项能够保证可重复读,可以避免脏读和不可重复读。
Serializable:该选项能够避免脏读、不可重复读和幻读现象,是最严格的隔离级别。
二、spring集成struts
1、应用服务器没有直接调用启动Spring的方法,但是应用服务器编译运行servlet,filter,listener,所以spring提供一个listener类,在服务器初始化的时候调用该类中的方法,所以在容器中配置如下:
<!-- 指定spring的配置文件,多个文件之间用逗号分隔 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans.xml</param-value>
</context-param>
<!-- 启动Spring容器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
2、我们把我们需要交给spring管理的类在beans.xml中配置:
如<bean name="/user/regist"
class="cn.sun.ssh.web.action.UserManagerAction">
<property name="dao" ref="userDAO"></property>
</bean>
但是action是被引擎调用的,我们如何把需要的action交给引擎呢,通过重写struts中的requestprocessor类中的processactioncreate方法,在spring中获得action后交给引擎管理,这也是struts的一个扩展机制。
所以我们要在struts-config.xml中配置controller
<controller>
<set-property property="processorClass" value="org.springframework.web.struts.DelegatingRequestProcessor"/>
</controller>
三、spring集成hibernate
1、spring集成hibernate时把dao和sessionfactory交给spring管理
posted @
2009-07-20 00:48 jadmin 阅读(59) |
评论 (0) |
编辑 收藏