在前面的示例中,使用的就是Spring支持的Java动态代理,也就是说代理的是接口,Spring默认使用的是Java的动态代理,这里就不再多作介绍。
2 CGLIB代理
正如前面所说,Spring也提供了对CGLIB代理的支持,主要改变就是设定ProxyFactoryBean的proxyTargetClass属性,将该属性值设定为true即可。因为要使用CGLIB代理,所以要将cglib-nodep-2.1_3.jar加入到CLASSPATH中,下面的示例中将使用前面的Around通知来实现。具体编写步骤如下:
(1)使用前面负责输出日志信息的类LogAround,该类实现了接口MethodInterceptor,重写了invoke()方法。LogAround.java的示例代码如下:
package com.gc.action; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.apache.log4j.Level; import org.apache.log4j.Logger; public class LogAround implements MethodInterceptor { private Logger logger=Logger.getLogger(this.getClass().getName()); public Object invoke(MethodInvocation mi)throws Throwable { logger.log(Level.INFO,mi.getArguments()[0]+"开始审核数据……"); try{ Object result=mi.proceed(); return result; } finally { logger.log(Level.INFO,mi.getArguments()[0]+"审核数据结束……"); } } }
假如把Spring的配置文件做一下修改,把id为logProxy的Bean增加一个属性proxyTargetClass,并设定该属性值为true。示例代码如下:
HelloWorld true log
(3)修改测试代码TestHelloWorld,使用Spring提供的代理类ProxyFactoryBean 实现日志的输出。TestHelloWorld.java的示例代码如下:
package com.gc.test; import com.gc.action.TimeBook; import com.gc.action.TimeBookProxy; import com.gc.impl.TimeBookInterface; public class TestHelloWorld { public static void main(String[ ] args) { //通过ApplicationContext获取配置文档 ApplicationContext actx=new FileSystemXmlApplicationContext("config.xml"); TimeBookInterface timeBookProxy = (TimeBookInterface)actx.getBean("logProxy"); timeBookProxy.doAuditing("张三"); } }
4)运行测试程序,可以看到有异常信息输出,如图5.10所示。
图5.10 异常信息输出
这是因为在Spring的配置文档中指定了要用CGLIB方式实现代理,但却没有把cglib-nodep-2.1_3.jar加入到CLASSPATH中去。按照第2章中介绍的方法,把spring-framework-2.0-m1/lib/cglib目录下的cglib-nodep-2.1_3.jar加入到CLASSPATH中。
(5)再次运行测试程序,可以看到使用CGLIB代理输出的日志信息,如图5.11所示。
图5.11 使用CGLIB代理输出的日志信息
使用CGLIB代理的好处就是不用再像使用Java动态代理那样去实现特定的接口,一个普通的Java类就可以了。