博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring学习(三)
阅读量:4023 次
发布时间:2019-05-24

本文共 22803 字,大约阅读时间需要 76 分钟。

Spring学习笔记(
14
)----使用CGLIB实现AOP功能
-----------------------------------------------
 
接着这上面的例子,在上面的例子中我们的UserManagerImpl类是实现了UserManager接口,如果UserManagerImpl没有实现任何接口要怎么办呢?应为创建代理对象时我们需要指定接口的。
  
 
 
Java代码 
1
.Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), 
2
.                                      targetObject.getClass().getInterfaces(), 
3
.                                     
this
); 
  
  
  
由于没有时间接口,因此我们是不能这样创建代理接口的,这是我们需要借助第三方包来实现。在spring中提供了cglib-nodep-
2
.1_3.jar包。我们通过cglib创建代理对象。
  
下面就通过实例演示通过cglib创建代理对象。
  
  
  
首先创建CGlibProxyFactory,实现MethodInterceptor接口,接口中有一个intercept方法,当代理对象的方法被调用时会调用这个方法。
  
 
 
Java代码 
1
.
package 
com.szy.spring; 
2
3
.
import 
java.lang.reflect.Method; 
4
.
import 
net.sf.cglib.proxy.Enhancer; 
5
.
import 
net.sf.cglib.proxy.MethodInterceptor; 
6
.
import 
net.sf.cglib.proxy.MethodProxy; 
7
8
9
.
public 
class 
CGlibProxyFactory
implements 
MethodInterceptor 
10
.{ 
11
.   
private 
Object targetObject; 
12
.     
13
.   
public 
Object newProxy(Object targetObject) 
14
.    { 
15
.       
this
.targetObject=targetObject; 
16
.        Enhancer enhancer=
new 
Enhancer(); 
17
.        enhancer.setSuperclass(
this
.targetObject.getClass()); 
18
.        enhancer.setCallback(
this
); 
19
.       
//返回代理对象 
20
.       
return 
enhancer.create(); 
21
.    } 
22
23
.   
/**
24.     * proxy        带来对象本身
25.     * method       被拦截到的方法
26.     * args          方法的参数
27.     * methodProxy  方法的代理对象
28.     */ 
29
.   
public 
Object intercept(Object proxy, Method method, Object[] args, 
30
.            MethodProxy methodProxy)
throws 
Throwable 
31
.    { 
32
.        checkSecurity(); 
33
.        Object ret=
null
34
.       
try 
35
.        { 
36
.           
//调用目标对象的真实方法 
37
.            ret=method.invoke(
this
.targetObject, args); 
38
.           
//ret接受存在的返回值,不存在返回值则为Null 
39
.        }
catch 
(Exception e) 
40
.        { 
41
.            e.printStackTrace(); 
42
.        } 
43
.       
return 
ret; 
44
.    } 
45
.   
public 
void 
checkSecurity() 
46
.    { 
47
.        System.out.println(
"--------UserManagerImpl.checkSecurity()----------"
); 
48
.    } 
49
.} 
  
  
  
其实整个代码很前面的很相似,只是创建代理对象的方法不一样。
  
测试代码:
  
 
 
Java代码 
1
.CGlibProxyFactory factory=
new 
CGlibProxyFactory(); 
2
.       
//创建代理对象,这是这个代理对象是UserManagerImpl的子类 
3
.        UserManagerImpl userManager=(UserManagerImpl)factory.newProxy(
new 
UserManagerImpl()); 
4
.        userManager.addUser(
"coolszy"
,
"kuka"
); 
  
  
  
上面演示的几个事例是不借助与任何框架的情况下实现AOP的方法。
 
 
 
 
 
 
 
Spring学习笔记(
15
)----使用Spring的注解方式实现AOP
-----------------------------------------------------
下面介绍使用Spring框架进行AOP编程。
  
首先我们需要导入需要的jar包:
  
1
.aspectjrt.jar
  
2
.aspectjweaver.jar
  
3
.cglib-nodep-
2
.1_3.jar
  
  
  
在spring中有两种方式实现面向切面编程,一种是基于XML配置,另一种是使用注解份额方式,在实际开放中我们可以任选其中的一种即可。
  
  
  
首先介绍下使用注解方式进行AOP开发。
  
要使用注解方式,我们需要打开注解处理器
  
 
 
Xml代码 
1
.<aop:aspectj-autoproxy/> 
  
我们还是使用前面介绍的接口:
  
  
  
 
 
Java代码 
1
.
package 
com.szy.spring; 
2
3
.
public 
interface 
UserManager 
4
.{ 
5
6
.   
public 
abstract 
void 
addUser(String username, String password); 
7
8
.   
public 
abstract 
void 
deleteUser(
int 
userId); 
9
10
.   
public 
abstract 
String findUser(
int 
userId); 
11
12
.   
public 
abstract 
void 
modifyUser(
int 
userId, String username, String password); 
13
14
.} 
  
  
  
实现这个接口:
  
 
 
Java代码 
1
.
package 
com.szy.spring; 
2
3
.
public 
class 
UserManagerImpl
implements 
UserManager  
4
.{ 
5
6
.   
public 
void 
addUser(String username, String password) 
7
.    { 
8
.        System.out.println(
"--------UserManagerImpl.addUser()----------"
); 
9
.    } 
10
11
.   
public 
void 
deleteUser(
int 
userId) 
12
.    { 
13
.        System.out.println(
"--------UserManagerImpl.deleteUser()----------"
); 
14
.    } 
15
16
.   
public 
String findUser(
int 
userId) 
17
.    { 
18
.        System.out.println(
"--------UserManagerImpl.findUser()----------"
); 
19
.       
return 
null
20
.    } 
21
22
.   
public 
void 
modifyUser(
int 
userId, String username, String password) 
23
.    { 
24
.        System.out.println(
"--------UserManagerImpl.modifyUser()----------"
); 
25
.    } 
26
.} 
  
  
  
下面我们定义一个切面类,由于我们使用的是注解方式,因此我们使用
@Aspect
来标识它是切面类。在切面类中我们要定义切入点,切入点是用来定义我们要拦截的方法。在切入点定义中使用了AOP表达式语言,下面通过实例简单解释一下:
  
  
  
 
 
表达式解释代码 
1
.
@Pointcut
(
"execution (* com.szy.spring..*.*(..))"
2
.execution:代表执行 
3
.第一个*:代表返回值类型,使用*代表任何类型的返回值 
4
.com.szy.spring:代表包名 
5
...:代表其底下的子包也进行拦截 
6
.第二个*:代表对哪个类进行拦截,*代表所有类 
7
.第三个*:代表方法 
8
.(..):代表方法的蚕食有无都可以 
  
  
  
现在我们要对UserManagerImpl类下的所有方法进行拦截,则切入点如下表示:
  
 
 
Java代码 
1
.
@Pointcut
(
"execution (* com.szy.spring.UserManagerImpl.*(..))"
2
3
.
private 
void 
anyMethod() 
//定义切入点 
4
. { 
5
. } 
  
  
  
其中切入点的名称是下面方法的名称aynMethod(),包括括号。
  
  
  
下面我们定义通知,通知分为前置通知、后置通知、意外通知、等。通知分为前置通知、后置通知、意外通知、最终通知和环绕通知等。
  
演示前置通知,
  
 
 
Java代码 
1
.
@Before
(
"anyMethod()"
)
//括号内为切入点名称 
2
public 
void 
doBefore() 
3
.  { 
4
.   System.out.println(
"----------------执行前置通知-----------------"
); 
5
.  } 
6
.  
7
@AfterReturning
(
"anyMethod()"
8
public 
void 
doAfterReturning() 
9
.  { 
10
.   System.out.println(
"----------------执行后置通知-----------------"
); 
11
.  } 
  
 
 
Java代码 
1
.
@After
(
"anyMethod()"
2
.
public 
void 
doAfter() 
3
. { 
4
.  System.out.println(
"----------------执行最终通知-----------------"
); 
5
. } 
6
.  
7
@AfterThrowing
(
"anyMethod()"
8
public 
void 
doAfterThrowing() 
9
.  { 
10
.   System.out.println(
"----------------执行意外通知-----------------"
); 
11
.  } 
12
.   
13
.
@Around
(
"anyMethod()"
14
.
public 
Object doAround(ProceedingJoinPoint pjp)
throws 
Throwable 
15
. { 
16
.  System.out.println(
"----------------进入判断方法-----------------"
); 
17
.  Object result=pjp.proceed(); 
//该方法必须被执行 
18
.  System.out.println(
"----------------退出判断方法-----------------"
); 
19
return 
result; 
20
. } 
  
  
  
 
我们把切面交给spring管理,要交给spring管理我们可以在配置文件同进行bean配置,或者使用扫描的方式。
  
 
 
Xml代码 
1
.<bean id=
"interceptor" 
class
=
"com.szy.spring.Interceptor"
/> 
  
 
下面我们进行测试
  
 
 
Java代码 
1
.ApplicationContext context=
new 
ClassPathXmlApplicationContext(
"applicationContext.xml"
); 
2
.        UserManager manager=(UserManager)context.getBean(
"userManager"
); 
3
.        manager.addUser(
"coolszy"
,
"kuka"
); 
  
  
  
按照我们的设计,输入的结果应为
  
----------------执行前置通知-----------------
----------------进入判断方法-----------------
--------UserManagerImpl.addUser()----------
----------------执行后置通知-----------------
----------------执行最终通知-----------------
----------------退出判断方法-----------------
 
 
 
 
 
 
Spring学习笔记(
16
)----使用Spring配置文件实现AOP
----------------------------------------------
 
前面介绍了使用注解的方式,下面介绍使用配置文件的方式实现AOP。
  
使用配置方式,Interceptor类中不包含任何注解。
  
 
 
Java代码 
1
.
package 
com.szy.spring; 
2
3
.
import 
org.aspectj.lang.ProceedingJoinPoint; 
4
5
.
public 
class 
Interceptor 
6
.{ 
7
.   
public 
void 
doBefore() 
8
.    { 
9
.        System.out.println(
"----------------执行前置通知-----------------"
); 
10
.    } 
11
.     
12
.   
public 
void 
doAfterReturning() 
13
.    { 
14
.        System.out.println(
"----------------执行后置通知-----------------"
); 
15
.    } 
16
.     
17
.   
public 
void 
doAfter() 
18
.    { 
19
.        System.out.println(
"----------------执行最终通知-----------------"
); 
20
.    } 
21
.     
22
.   
public 
void 
doAfterThrowing() 
23
.    { 
24
.        System.out.println(
"----------------执行意外通知-----------------"
); 
25
.    } 
26
.     
27
.   
public 
Object doAround(ProceedingJoinPoint pjp)
throws 
Throwable 
28
.    { 
29
.        System.out.println(
"----------------进入判断方法-----------------"
); 
30
.        Object result=pjp.proceed(); 
//该方法必须被执行 
31
.        System.out.println(
"----------------退出判断方法-----------------"
); 
32
.       
return 
result; 
33
.    } 
34
.} 
  
 
紧着这我们在配置文件中配置切面、切入点、通知等:
  
 
 
Xml代码 
1
.<bean id=
"aspetbean" 
class
=
"com.szy.spring.Interceptor"
/> 
2
.    <aop:config> 
3
.        <aop:aspect id=
"aspet" 
ref=
"aspetbean"
4
.            <aop:pointcut id=
"cut" 
expression=
"execution (* com.szy.spring.UserManagerImpl.*(..))"
/> 
5
.            <aop:before pointcut-ref=
"cut" 
method=
"doBefore"
/> 
6
.            <aop:after-returning pointcut-ref=
"cut" 
method=
"doAfterReturning"
/> 
7
.            <aop:after pointcut-ref=
"cut" 
method=
"doAfter"
/> 
8
.            <aop:after-throwing pointcut-ref=
"cut" 
method=
"doAfterThrowing"
/> 
9
.            <aop:around pointcut-ref=
"cut" 
method=
"doAround"
/> 
10
.        </aop:aspect> 
11
.    </aop:config> 
  
 
运行测试代码输入正常结果。
  
在实际开发中AOP一般用于权限设置等。
  
  
 
 
 
Spring学习笔记(
14
)----使用CGLIB实现AOP功能
-----------------------------------------------
 
接着这上面的例子,在上面的例子中我们的UserManagerImpl类是实现了UserManager接口,如果UserManagerImpl没有实现任何接口要怎么办呢?应为创建代理对象时我们需要指定接口的。
  
 
 
Java代码 
1
.Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), 
2
.                                      targetObject.getClass().getInterfaces(), 
3
.                                     
this
); 
  
  
  
由于没有时间接口,因此我们是不能这样创建代理接口的,这是我们需要借助第三方包来实现。在spring中提供了cglib-nodep-
2
.1_3.jar包。我们通过cglib创建代理对象。
  
下面就通过实例演示通过cglib创建代理对象。
  
  
  
首先创建CGlibProxyFactory,实现MethodInterceptor接口,接口中有一个intercept方法,当代理对象的方法被调用时会调用这个方法。
  
 
 
Java代码 
1
.
package 
com.szy.spring; 
2
3
.
import 
java.lang.reflect.Method; 
4
.
import 
net.sf.cglib.proxy.Enhancer; 
5
.
import 
net.sf.cglib.proxy.MethodInterceptor; 
6
.
import 
net.sf.cglib.proxy.MethodProxy; 
7
8
9
.
public 
class 
CGlibProxyFactory
implements 
MethodInterceptor 
10
.{ 
11
.   
private 
Object targetObject; 
12
.     
13
.   
public 
Object newProxy(Object targetObject) 
14
.    { 
15
.       
this
.targetObject=targetObject; 
16
.        Enhancer enhancer=
new 
Enhancer(); 
17
.        enhancer.setSuperclass(
this
.targetObject.getClass()); 
18
.        enhancer.setCallback(
this
); 
19
.       
//返回代理对象 
20
.       
return 
enhancer.create(); 
21
.    } 
22
23
.   
/**
24.     * proxy        带来对象本身
25.     * method       被拦截到的方法
26.     * args          方法的参数
27.     * methodProxy  方法的代理对象
28.     */ 
29
.   
public 
Object intercept(Object proxy, Method method, Object[] args, 
30
.            MethodProxy methodProxy)
throws 
Throwable 
31
.    { 
32
.        checkSecurity(); 
33
.        Object ret=
null
34
.       
try 
35
.        { 
36
.           
//调用目标对象的真实方法 
37
.            ret=method.invoke(
this
.targetObject, args); 
38
.           
//ret接受存在的返回值,不存在返回值则为Null 
39
.        }
catch 
(Exception e) 
40
.        { 
41
.            e.printStackTrace(); 
42
.        } 
43
.       
return 
ret; 
44
.    } 
45
.   
public 
void 
checkSecurity() 
46
.    { 
47
.        System.out.println(
"--------UserManagerImpl.checkSecurity()----------"
); 
48
.    } 
49
.} 
  
  
  
其实整个代码很前面的很相似,只是创建代理对象的方法不一样。
  
测试代码:
  
 
 
Java代码 
1
.CGlibProxyFactory factory=
new 
CGlibProxyFactory(); 
2
.       
//创建代理对象,这是这个代理对象是UserManagerImpl的子类 
3
.        UserManagerImpl userManager=(UserManagerImpl)factory.newProxy(
new 
UserManagerImpl()); 
4
.        userManager.addUser(
"coolszy"
,
"kuka"
); 
  
  
  
上面演示的几个事例是不借助与任何框架的情况下实现AOP的方法。
 
 
 
 
 
 
 
Spring学习笔记(
15
)----使用Spring的注解方式实现AOP
-----------------------------------------------------
下面介绍使用Spring框架进行AOP编程。
  
首先我们需要导入需要的jar包:
  
1
.aspectjrt.jar
  
2
.aspectjweaver.jar
  
3
.cglib-nodep-
2
.1_3.jar
  
  
  
在spring中有两种方式实现面向切面编程,一种是基于XML配置,另一种是使用注解份额方式,在实际开放中我们可以任选其中的一种即可。
  
  
  
首先介绍下使用注解方式进行AOP开发。
  
要使用注解方式,我们需要打开注解处理器
  
 
 
Xml代码 
1
.<aop:aspectj-autoproxy/> 
  
我们还是使用前面介绍的接口:
  
  
  
 
 
Java代码 
1
.
package 
com.szy.spring; 
2
3
.
public 
interface 
UserManager 
4
.{ 
5
6
.   
public 
abstract 
void 
addUser(String username, String password); 
7
8
.   
public 
abstract 
void 
deleteUser(
int 
userId); 
9
10
.   
public 
abstract 
String findUser(
int 
userId); 
11
12
.   
public 
abstract 
void 
modifyUser(
int 
userId, String username, String password); 
13
14
.} 
  
  
  
实现这个接口:
  
 
 
Java代码 
1
.
package 
com.szy.spring; 
2
3
.
public 
class 
UserManagerImpl
implements 
UserManager  
4
.{ 
5
6
.   
public 
void 
addUser(String username, String password) 
7
.    { 
8
.        System.out.println(
"--------UserManagerImpl.addUser()----------"
); 
9
.    } 
10
11
.   
public 
void 
deleteUser(
int 
userId) 
12
.    { 
13
.        System.out.println(
"--------UserManagerImpl.deleteUser()----------"
); 
14
.    } 
15
16
.   
public 
String findUser(
int 
userId) 
17
.    { 
18
.        System.out.println(
"--------UserManagerImpl.findUser()----------"
); 
19
.       
return 
null
20
.    } 
21
22
.   
public 
void 
modifyUser(
int 
userId, String username, String password) 
23
.    { 
24
.        System.out.println(
"--------UserManagerImpl.modifyUser()----------"
); 
25
.    } 
26
.} 
  
  
  
下面我们定义一个切面类,由于我们使用的是注解方式,因此我们使用
@Aspect
来标识它是切面类。在切面类中我们要定义切入点,切入点是用来定义我们要拦截的方法。在切入点定义中使用了AOP表达式语言,下面通过实例简单解释一下:
  
  
  
 
 
表达式解释代码 
1
.
@Pointcut
(
"execution (* com.szy.spring..*.*(..))"
2
.execution:代表执行 
3
.第一个*:代表返回值类型,使用*代表任何类型的返回值 
4
.com.szy.spring:代表包名 
5
...:代表其底下的子包也进行拦截 
6
.第二个*:代表对哪个类进行拦截,*代表所有类 
7
.第三个*:代表方法 
8
.(..):代表方法的蚕食有无都可以 
  
  
  
现在我们要对UserManagerImpl类下的所有方法进行拦截,则切入点如下表示:
  
 
 
Java代码 
1
.
@Pointcut
(
"execution (* com.szy.spring.UserManagerImpl.*(..))"
2
3
.
private 
void 
anyMethod() 
//定义切入点 
4
. { 
5
. } 
  
  
  
其中切入点的名称是下面方法的名称aynMethod(),包括括号。
  
  
  
下面我们定义通知,通知分为前置通知、后置通知、意外通知、等。通知分为前置通知、后置通知、意外通知、最终通知和环绕通知等。
  
演示前置通知,
  
 
 
Java代码 
1
.
@Before
(
"anyMethod()"
)
//括号内为切入点名称 
2
public 
void 
doBefore() 
3
.  { 
4
.   System.out.println(
"----------------执行前置通知-----------------"
); 
5
.  } 
6
.  
7
@AfterReturning
(
"anyMethod()"
8
public 
void 
doAfterReturning() 
9
.  { 
10
.   System.out.println(
"----------------执行后置通知-----------------"
); 
11
.  } 
  
 
 
Java代码 
1
.
@After
(
"anyMethod()"
2
.
public 
void 
doAfter() 
3
. { 
4
.  System.out.println(
"----------------执行最终通知-----------------"
); 
5
. } 
6
.  
7
@AfterThrowing
(
"anyMethod()"
8
public 
void 
doAfterThrowing() 
9
.  { 
10
.   System.out.println(
"----------------执行意外通知-----------------"
); 
11
.  } 
12
.   
13
.
@Around
(
"anyMethod()"
14
.
public 
Object doAround(ProceedingJoinPoint pjp)
throws 
Throwable 
15
. { 
16
.  System.out.println(
"----------------进入判断方法-----------------"
); 
17
.  Object result=pjp.proceed(); 
//该方法必须被执行 
18
.  System.out.println(
"----------------退出判断方法-----------------"
); 
19
return 
result; 
20
. } 
  
  
  
 
我们把切面交给spring管理,要交给spring管理我们可以在配置文件同进行bean配置,或者使用扫描的方式。
  
 
 
Xml代码 
1
.<bean id=
"interceptor" 
class
=
"com.szy.spring.Interceptor"
/> 
  
 
下面我们进行测试
  
 
 
Java代码 
1
.ApplicationContext context=
new 
ClassPathXmlApplicationContext(
"applicationContext.xml"
); 
2
.        UserManager manager=(UserManager)context.getBean(
"userManager"
); 
3
.        manager.addUser(
"coolszy"
,
"kuka"
); 
  
  
  
按照我们的设计,输入的结果应为
  
----------------执行前置通知-----------------
----------------进入判断方法-----------------
--------UserManagerImpl.addUser()----------
----------------执行后置通知-----------------
----------------执行最终通知-----------------
----------------退出判断方法-----------------
 
 
 
 
 
 
Spring学习笔记(
16
)----使用Spring配置文件实现AOP
----------------------------------------------
 
前面介绍了使用注解的方式,下面介绍使用配置文件的方式实现AOP。
  
使用配置方式,Interceptor类中不包含任何注解。
  
 
 
Java代码 
1
.
package 
com.szy.spring; 
2
3
.
import 
org.aspectj.lang.ProceedingJoinPoint; 
4
5
.
public 
class 
Interceptor 
6
.{ 
7
.   
public 
void 
doBefore() 
8
.    { 
9
.        System.out.println(
"----------------执行前置通知-----------------"
); 
10
.    } 
11
.     
12
.   
public 
void 
doAfterReturning() 
13
.    { 
14
.        System.out.println(
"----------------执行后置通知-----------------"
); 
15
.    } 
16
.     
17
.   
public 
void 
doAfter() 
18
.    { 
19
.        System.out.println(
"----------------执行最终通知-----------------"
); 
20
.    } 
21
.     
22
.   
public 
void 
doAfterThrowing() 
23
.    { 
24
.        System.out.println(
"----------------执行意外通知-----------------"
); 
25
.    } 
26
.     
27
.   
public 
Object doAround(ProceedingJoinPoint pjp)
throws 
Throwable 
28
.    { 
29
.        System.out.println(
"----------------进入判断方法-----------------"
); 
30
.        Object result=pjp.proceed(); 
//该方法必须被执行 
31
.        System.out.println(
"----------------退出判断方法-----------------"
); 
32
.       
return 
result; 
33
.    } 
34
.} 
  
 
紧着这我们在配置文件中配置切面、切入点、通知等:
  
 
 
Xml代码 
1
.<bean id=
"aspetbean" 
class
=
"com.szy.spring.Interceptor"
/> 
2
.    <aop:config> 
3
.        <aop:aspect id=
"aspet" 
ref=
"aspetbean"
4
.            <aop:pointcut id=
"cut" 
expression=
"execution (* com.szy.spring.UserManagerImpl.*(..))"
/> 
5
.            <aop:before pointcut-ref=
"cut" 
method=
"doBefore"
/> 
6
.            <aop:after-returning pointcut-ref=
"cut" 
method=
"doAfterReturning"
/> 
7
.            <aop:after pointcut-ref=
"cut" 
method=
"doAfter"
/> 
8
.            <aop:after-throwing pointcut-ref=
"cut" 
method=
"doAfterThrowing"
/> 
9
.            <aop:around pointcut-ref=
"cut" 
method=
"doAround"
/> 
10
.        </aop:aspect> 
11
.    </aop:config> 
  
 
运行测试代码输入正常结果。
  
在实际开发中AOP一般用于权限设置等。
  
  
 
 
 
 
Spring学习笔记(
17
)----使用Spring注解方式管理事务
--------------------------------------------------
使用Spring+JDBC集成步骤如下:
  
 
*配置数据源,例如:
  
 
 
Xml代码 
1
.<bean id=
"dataSource" 
class
=
"org.apache.commons.dbcp.BasicDataSource" 
destroy-method=
"close"
2
.            <property name=
"driverClassName" 
value=
"com.mysql.jdbc.Driver"
/> 
3
.            <property name=
"url" 
value=
"jdbc:mysql://localhost:3306/test"
/> 
4
.            <property name=
"username" 
value=
"root"
/> 
5
.            <property name=
"password" 
value=
"123456"
/> 
6
.            <!-- 连接池启动时的初始值 --> 
7
.            <property name=
"initialSize" 
value=
"1"
/> 
8
.            <!-- 连接池的最大值 --> 
9
.            <property name=
"maxActive" 
value=
"100"
/> 
10
.            <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 --> 
11
.            <property name=
"maxIdle" 
value=
"2"
/> 
12
.            <!--  最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 --> 
13
.            <property name=
"minIdle" 
value=
"1"
/> 
14
.        </bean> 
  
 
*配置事务,配置事务时,需要在xml配置文件中引入用于声明事务的tx命名空间,事务的配置有两种方式:注解方式和基于XML配置的方式
  
  
  
下面演示下使用Spring注解方式管理事务
  
首先在配置文件中配置Spring提供的事务管理器
  
 
 
Xml代码 
1
.<bean id=
"txManager" 
class
=
"org.springframework.jdbc.datasource.DataSourceTransactionManager"
2
.            <!-- 指定数据源 --> 
3
.            <property name=
"dataSource" 
ref=
"dataSource"
/> 
4
.        </bean> 
  
 
由于会使用注解方式,因此我们要打开注解处理器,对注解进行解析
  
 
 
Xml代码 
1
.<tx:annotation-driven transaction-manager=
"txManager"
/> 
  
  
  
这样我们的配置文件配置完成,下面我们在Mysql中建立一张表,
  
 
 
Sql代码 
1
.create table users 
2
.(                    
3
. id
int
(
11
) not
null 
auto_increment,   
4
. username varchar(
20
) not
null
,        
5
. primary key (id)                    
6
.)  
  
  
  
根据数据库,我们创建javabean
  
 
 
Java代码 
1
.
package 
com.szy.spring.bean; 
2
.
/**
3. * @author  coolszy
4. * @time    Dec 6, 2009 2:13:33 PM
5. */ 
6
.
public 
class 
User 
7
.{ 
8
.   
private 
int 
id; 
9
.   
private 
String username; 
10
.   
public 
int 
getId() 
11
.    { 
12
.       
return 
id; 
13
.    } 
14
.   
public 
void 
setId(
int 
id) 
15
.    { 
16
.       
this
.id = id; 
17
.    } 
18
.   
public 
String getUsername() 
19
.    { 
20
.       
return 
username; 
21
.    } 
22
.   
public 
void 
setUsername(String username) 
23
.    { 
24
.       
this
.username = username; 
25
.    } 
26
.}    
  
  
  
然后创建DAO接口,在DAO中提供几个方法:
  
 
 
Java代码 
1
.
package 
com.szy.spring.dao; 
2
3
.
import 
java.util.List; 
4
5
.
import 
com.szy.spring.bean.User; 
6
7
.
public 
interface 
UserDAO 
8
.{ 
9
.   
public 
void 
save(User user); 
10
.   
public 
void 
update(User user); 
11
.    Public User  getUser(
int 
id); 
12
.   
public 
void 
delete(
int 
id); 
13
.   
public 
List<User> getAllUsers(); 
14
.}    
  
  
  
实现这个接口
  
  
  
 
 
Java代码 
1
.
package 
com.szy.spring.dao.impl; 
2
3
.
import 
java.util.List; 
4
5
.
import 
com.szy.spring.bean.User; 
6
.
import 
com.szy.spring.service.UserService; 
7
8
.
/**
9. * @author  coolszy
10. * @time    Dec 6, 2009 2:19:22 PM
11. */ 
12
.
public 
class 
UserDAOImpl
implements 
UserDAO 
13
.{ 
14
15
.   
public 
void 
delete(
int 
id) 
16
.    { 
17
18
.    } 
19
20
.   
public 
List<User> getAllUsers() 
21
.    { 
22
.       
return 
null
23
.    } 
24
25
.   
public 
User getUser(
int 
id) 
26
.    { 
27
28
.    } 
29
30
.   
public 
void 
save(User user) 
31
.    { 
32
33
.    } 
34
35
.   
public 
void 
update(User user) 
36
.    { 
37
38
.    } 
39
40
.}    
  
  
  
下面把这个类交给Spring管理
  
 
 
Xml代码 
1
.<bean id=
"userDAO" 
class
=
"com.szy.spring.dao.impl.UserDAOImpl"
/>   
  
 
由于要通过数据源对表进行操作,因此在DAO中添加数据源。
  
 
 
Java代码 
1
.
private 
DataSource dataSource; 
2
3
.   
public 
void 
setDataSource(DataSource dataSource) 
4
.    { 
5
.       
this
.dataSource = dataSource; 
6
.    }    
  
  
  
然后在配置文件中进行配置
  
 
 
Xml代码 
1
.<bean id=
"userDAO" 
class
=
"com.szy.spring.service.impl.UserDAOImpl"
2
.            <property name=
"dataSource" 
ref=
"dataSource"
/> 
3
.        </bean>    
  
  
  
这样我们就把数据源注入到类中。
  
在UserDAOImpl类中我们提供了dataSource,这样我们就可以对数据库进行操作,但是不推荐直接使用dataSource,建议使用JdbcTemplate
  
 
 
Java代码 
1
.
private 
JdbcTemplate jdbcTemplate; 
2
.   
public 
void 
setDataSource(DataSource dataSource) 
3
.    { 
4
.       
//this.dataSource = dataSource; 
5
.       
this
.jdbcTemplate=
new 
JdbcTemplate(dataSource); 
6
.    }    
  
 
下面我们使用jdbcTemplate对数据库进行增删改查,详细代码见附件。
  
 
 
Java代码 
1
.
package 
com.szy.spring.dao.impl; 
2
3
.
import 
java.util.List; 
4
5
.
import 
javax.sql.DataSource; 
6
7
.
import 
org.springframework.jdbc.core.JdbcTemplate; 
8
9
.
import 
com.szy.spring.bean.User; 
10
.
import 
com.szy.spring.dao.UserDAO; 
11
12
.
/**
13. * @author  coolszy
14. * @time    Dec 6, 2009 2:19:22 PM
15. */ 
16
.
public 
class 
UserDAOImpl
implements 
UserDAO 
17
.{ 
18
.   
//private DataSource dataSource; 
19
.   
private 
JdbcTemplate jdbcTemplate; 
20
.   
public 
void 
setDataSource(DataSource dataSource) 
21
.    { 
22
.       
//this.dataSource = dataSource; 
23
.       
this
.jdbcTemplate=
new 
JdbcTemplate(dataSource); 
24
.    } 
25
26
.   
public 
void 
delete(
int 
id) 
27
.    { 
28
.        jdbcTemplate.update(
"delete from users where id=?"
,
new 
Object[]{id}, 
29
.               
new 
int
[]{java.sql.Types.INTEGER}); 
30
.    } 
31
32
.   
public 
List<User> getAllUsers() 
33
.    { 
34
.       
return 
(List<User>)jdbcTemplate.query(
"select * from users"
,
new 
UserRowMapper()); 
35
.    } 
36
37
.   
public 
User getUser(
int 
id) 
38
.    { 
39
.       
return 
(User)jdbcTemplate.queryForObject(
"select * from users where id=?"
,
new 
Object[]{id},  
40
.               
new 
int
[]{java.sql.Types.INTEGER},
new 
UserRowMapper()); 
41
42
.    } 
43
44
.   
public 
void 
save(User user) 
45
.    {  
46
.        jdbcTemplate.update(
"insert into users(username) values(?)"
,
new 
Object[]{user.getUsername()}, 
47
.               
new 
int
[]{java.sql.Types.VARCHAR}); 
48
49
.    } 
50
51
.   
public 
void 
update(User user) 
52
.    { 
53
.        jdbcTemplate.update(
"update users set username=? where id=?"
,
new 
Object[]{user.getUsername(),user.getId()}, 
54
.               
new 
int
[]{java.sql.Types.VARCHAR, java.sql.Types.INTEGER}); 
55
56
.    } 
57
58
.}    
  
 
编写测试代码,代码运行正常。
  
在我们实现的每个方法中如delete()方法,如果delete方法是这样
  
 
 
Java代码 
1
.
public 
void 
delete(
int 
id) 
2
.    { 
3
.        jdbcTemplate.update(
"delete from users where id=?"
,
new 
Object[]{id}, 
4
.               
new 
int
[]{java.sql.Types.INTEGER}); 
5
.jdbcTemplate.update(
"delete from users where id=?"
,
new 
Object[]{id}, 
6
.               
new 
int
[]{java.sql.Types.INTEGER}); 
7
8
.    } 
9
.     
  
 
这样每条语句都会在各自的事务中执行,并不能保证在同一使用中执行,为了保证在同一事务中执行,我们应使用Spring容器提供的声明事务,我们在UserDAOImpl 类上加入
@Transactional
,表示该类受Spring事务管理。如果该类中每个方法不需要事务管理,如getUser方法,则在该方法前加入
  
 
 
Java代码 
1
.
@Transactional
(propagation=Propagation.NOT_SUPPORTED) 
  
  
  
  
  
PS:在上面的配置文件中我们在配置文件中指明了驱动类等信息,如果我们想写在配置文件中要怎么配置能,首先我们编写配置文件,
  
 
 
Jdbc.properties代码 
1
.driverClassName=com.mysql.jdbc.Driver 
2
.url=jdbc\:mysql\:
//localhost\:3306/test 
3
.username=root 
4
.password=
123456 
5
.initialSize=
1 
6
.maxActive=
100 
7
.maxIdle=
2 
8
.minIdle=
1    
  
 
然后Spring的配置文件需进行如下配置:
  
 
 
Xml代码 
1
.<context:property-placeholder location=
"classpath:jdbc.properties"
/> 
2
.        <bean id=
"dataSource" 
class
=
"org.apache.commons.dbcp.BasicDataSource" 
destroy-method=
"close"
3
.            <property name=
"driverClassName" 
value=
"${driverClassName}"
/> 
4
.            <property name=
"url" 
value=
"${url}"
/> 
5
.            <property name=
"username" 
value=
"${username}"
/> 
6
.            <property name=
"password" 
value=
"${password}"
/> 
7
.            <property name=
"initialSize" 
value=
"${initialSize}"
/> 
8
.            <property name=
"maxActive" 
value=
"${maxActive}"
/> 
9
.            <property name=
"maxIdle" 
value=
"${maxIdle}"
/> 
10
.            <property name=
"minIdle" 
value=
"${minIdle}"
/> 
11
.        </bean>    
  
  
这样就可以从属性文件中读取到配置信息。
  
  
 
 
 
 
 
Spring学习笔记(
18
)----使用Spring配置文件实现事务管理
-------------------------------------------------------
由于我们要拦截UserDAOImpl中的方法,因此我们需要在配置文件中配置信息,在配置文件中使用了AOP技术来拦截方法。
  
 
 
Xml代码 
1
.<aop:config> 
2
.    <aop:pointcut id=
"transactionPointcut" 
expression=
"execution(* com.szy.spring.dao.impl..*.*(..))"
/> 
3
.    <aop:advisor advice-ref=
"txAdvice" 
pointcut-ref=
"transactionPointcut"
/> 
4
.  </aop:config>  
5
.  <tx:advice id=
"txAdvice" 
transaction-manager=
"txManager"
6
.     <tx:attributes> 
7
.      <!-- 如果连接的方法是以get开头的方法,则不使用事务 --> 
8
.       <tx:method name=
"get*" 
read-only=
"true" 
propagation=
"NOT_SUPPORTED"
/> 
9
.       <tx:method name=
"*"
/> 
10
.     </tx:attributes> 
11
.  </tx:advice> 
  
   
  
这样Spring就能对这个类进行事务管理。
  
  
  
下面我们测试下数据库操作是否在同一事务中执行。
  
假设我们的delete方法如下:
  
 
 
Java代码 
1
.
public 
void 
delete(
int 
id) 
2
. { 
3
.  jdbcTemplate.update(
"delete from users where id=?"
,
new 
Object[]{id}, 
4
.   
new 
int
[]{java.sql.Types.INTEGER}); 
5
.  jdbcTemplate.update(
"delete from users1 where id=10"
); 
6
. } 
  
  
  
  
  
在第二条删除语句中,users1表是不存在的,如果两次update语句是在两个事务中执行,则第一条能成功执行,并且数据库中该id的记录已经被删除,而第二条由于不存在该表不能正常删除。如果在同一事务中执行,由于第二条update出错,数据库中不能删除任何记录。
  
测试代码:
  
 
 
Java代码 
1
.
@Test 
2
.
public 
void 
testDelete() 
3
. { 
4
.  userDAO.delete(
5
); 
5
. } 
  
  
 
程序报错,同时id=
5
的记录没有被删除。如果我们把配置文件中关于事务配置的信息给注释掉,再次测试,程序同样报错,但是id=
5
的记录被成功删除掉,这说明这两条update语句是在两个不同的事务中运行。
  
  
  
PS:在平时开发中,Spring团队建议使用注解的方式进行配置,这样配置文件显得精简,同时也会做到精确控制。

转载地址:http://esfbi.baihongyu.com/

你可能感兴趣的文章
spring JdbcTemplate 的若干问题
查看>>
Servlet和JSP的线程安全问题
查看>>
GBK编码下jQuery Ajax中文乱码终极暴力解决方案
查看>>
jQuery性能优化指南
查看>>
利用spring的mock类进行单元测试
查看>>
spring的beanFactory和factoryBean
查看>>
性能测试中用LambdaProbe监控Tomcat Tomcat和Probe的配置
查看>>
Java RMI之HelloWorld篇
查看>>
Oracle 物化视图
查看>>
利用VMware搭建虚拟开发环境及VMware虚拟机上网
查看>>
spring系列之 回调函数的使用
查看>>
Java中的枚举(一)
查看>>
Java中的枚举(二)
查看>>
request.getInputStream()读取post传递的xml文件问题
查看>>
用Java实现断点续传(HTTP)
查看>>
Oracle树查询及相关函数
查看>>
Struts2中配置Servlet详解
查看>>
weblogic10和hibernate3 冲突解决方案
查看>>
WebLogic部署SSH2项目的小结
查看>>
JS+Struts2多文件上传完整示例
查看>>