本节中,咱们经过具体的实例说明基于CGLib字节码动态代理没法享受Spring AOP事务加强的特殊方法。 java
package com.baobaotao.special; import org.springframework.stereotype.Service; @Service("userService") public class UserService { //① private方法因访问权限的限制,没法被子类覆盖 private void method1() { System.out.println("method1"); } //② final方法没法被子类覆盖 public final void method2() { System.out.println("method2"); } //③ static是类级别的方法,没法被子类覆盖 public static void method3() { System.out.println("method3"); } //④ public方法能够被子类覆盖,所以能够被动态字节码加强 public void method4() { System.out.println("method4"); } }
Spring经过CGLib动态代理技术对UserService Bean实施AOP事务加强的关键配置,具体以下所示: mysql
… <aop:config proxy-target-class="true"><!-- ①显式使用CGLib动态代理 --> <!-- ②但愿对UserService全部方法实施事务加强 --> <aop:pointcut id="serviceJdbcMethod" expression="execution(* com.baobaotao.special.UserService.*(..))"/> <aop:advisor pointcut-ref="serviceJdbcMethod" advice-ref="jdbcAdvice" order="0"/> </aop:config> <tx:advice id="jdbcAdvice" transaction-manager="jdbcManager"> <tx:attributes> <tx:method name="*"/> </tx:attributes> </tx:advice> …
在①处,咱们经过proxy-target-class="true"显式使用CGLib动态代理技术,在②处经过AspjectJ切点表达式表达UserService全部的方法,但愿对UserService全部方法都实施Spring AOP事务加强。
在UserService添加一个可执行的方法,以下所示:spring
package com.baobaotao.special; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Service; @Service("userService") public class UserService { … public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("user/special/applicationContext.xml"); UserService service = (UserService) ctx.getBean("userService"); System.out.println("before method1"); service.method1(); System.out.println("after method1"); System.out.println("before method2"); service.method2(); System.out.println("after method2"); System.out.println("before method3"); service.method3(); System.out.println("after method3"); System.out.println("before method4"); service.method4(); System.out.println("after method4"); } }
在运行UserService以前,将Log4J日志级别设置为DEBUG,运行以上代码查看输出日志,以下所示:sql
序 号 |
动态代理策略 |
不能被事务加强的方法 |
1 | 基于接口的动态代理 | 除public外的其余全部的方法,此外public static也不能被加强 |
2 | 基于CGLib的动态代理 | private、static、final的方法 |