本节中,我们通过具体的实例说明基于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事务增强。 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添加一个可执行的方法,如下所示:
在运行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