Spring的事务管理难点剖析(6):特殊方法成漏网之鱼(一)

2014-11-24 08:46:58 · 作者: · 浏览: 2


本节中,我们通过具体的实例说明基于CGLib字节码动态代理无法享受Spring AOP事务增强的特殊方法。

01 package com.baobaotao.special;

02 import org.springframework.stereotype.Service;

03 @Service("userService")

04 public class UserService {

05

06 //① private方法因访问权限的限制,无法被子类覆盖

07 private void method1() {

08 System.out.println("method1");

09 }

10

11 //② final方法无法被子类覆盖

12 public final void method2() {

13 System.out.println("method2");

14 }

15

16 //③ static是类级别的方法,无法被子类覆盖

17 public static void method3() {

18 System.out.println("method3");

19 }

20

21 //④ public方法可以被子类覆盖,因此可以被动态字节码增强

22 public void method4() {

23 System.out.println("method4");

24 }

25 }

Spring通过CGLib动态代理技术对UserService Bean实施AOP事务增强的关键配置,具体如下所示:

01

02

03

04

05

06 expression="execution(* com.baobaotao.special.UserService.*(..))"/>

07

08

09

10

11

12

13

14 …

在①处,我们通过proxy-target-class="true"显式使用CGLib动态代理技术,在②处通过AspjectJ切点表达式表达UserService所有的方法,希望对UserService所有方法都实施Spring AOP事务增强。
在UserService添加一个可执行的方法,如下所示:

01 package com.baobaotao.special;

02 import org.springframework.context.ApplicationContext;

03 import org.springframework.context.support.ClassPathXmlApplicationContext;

04 import org.springframework.stereotype.Service;

05

06 @Service("userService")

07 public class UserService {

08 …

09 public static void main(String[] args) {

10 ApplicationContext ctx =

11 new ClassPathXmlApplicationContext("user/special/applicationContext.xml");

12 UserService service = (UserService) ctx.getBean("userService");

13

14 System.out.println("before method1");

15 service.method1();

16 System.out.println("after method1");

17

18 System.out.println("before method2");

19 service.method2();

20 System.out.println("after method2");

21

22 System.out.println("before method3");

23 service.method3();

24 System.out.println("after method3");

25

26 System.out.println("before method4");

27 service.method4();

28 System.out.println("after method4");

29

30 }

31 }


在运行UserService之前,将Log4J日志级别设置为DEBUG,运行以上代码查看输出日志,如下所示:

引用

①未启用事务
before method1
in method1
after method1

②未启用事务
before method2
in method2
after method2

③未启用事务
before method3
in method3
after method3

④启用事务
before method4
Creating new transaction with name [com.baobaotao.special.UserService.method4]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT

in method4
Initiating transaction commit
Committing JDBC transaction on Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost , MySQL-AB JDBC Driver]
Releasing JDBC Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost , MySQL-AB JDBC Driver] after transaction
Returning JDBC Connection to DataSource
after method4

⑤未用事务
before method5
in method5
after method5

⑥启用事务
before method6
Creating new transaction with name [com.baobaotao.special.UserService.method6]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT

in method6
Initiatin