AOP(Aspect-Oriented Programming,面向切面编程)是对面向对象开发的一种补充,它允许开发人员在不改变原来模型的基础上动态地修改模型从而满足新的需求。例如,在不改变原来业务逻辑模型的基础上可以动态地增加日志、安全或异常处理的功能。
下面介绍一个在Spring中使用AOP编程的简单例子。
(1)创建一个接口以及实现这个接口的类。TestAOPIn.java内容如下所示。
public interface TestAOPIn{ public void doSomething(); } |
TestAOPImpl.java内容如下所示。
public class TestAOPImpl implements TestAOPIn{ public void doSomething(){ System.out.println("TestAOPImpl:doSomething"); } } |
(2)配置SpringConfig.xml,使得这个类的实例化对象可以被注入到使用这个对象的Test类中。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="testAOPBean" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name=”target”> <bean class=”testAOPIn” singleton=”false” /> </property> </bean> </beans> |
(3)在完成配置文件后,编写测试代码如下所示。
import org.springframework.context.ApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; public class Test { public static void main(String[] args) { ApplicationContext ctx = new FileSystemXmlApplicationContext("SpringConfig.xml "); TestAOPIn t = (TestAOPIn)ctx.getBean("testAOPBean"); t.doSomething(); } } |
程序输出结果为:
TestAOPImpl:doSomething |
当编写完这个模块后,开发人员需要增加对doSomething()方法调用的跟踪,也就是说要跟踪该方法什么时候被调用的以及什么时候调用结束的等内容。当然,使用传统的方法也可以实现该功能,但是却会产生额外的开销,即需要修改已存在的模块。所以,可以采用如下的方式来实现这个功能。
public class TestAOPImpl implements TestAOPIn{ public void doSomething(){ System.out.println("beginCall doSomething"); System.out.println("TestAOPImpl:doSomething"); System.out.println("endCall doSomething"); } } |
此时可以采用AOP的方式来完成。它在不修改原有模块的前提下可以完成相同的功能。实现原理如下图所示。
为此需要提供用来跟踪函数调用的类,traceBeforeCall.java文件内容如下所示。
public class traceBeforeCall implements MethodBeforeAdvice { public void beforeCall (Method arg0, Object[] arg1, Object arg2) throws Throwable { System.out.println("beginCall doSomething "); } } |
traceEndCall.java文件内容如下所示。
import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; public class traceEndCall implements AfterReturningAdvice { public void afterCall(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable { System.out.println("endCall doSomething); } } |
只需要在配置文件中配置在调用doSomething()方法之前需要调用traceBeforeCall类的beforeCall()方法,在调用doSomething()方法之后需要调用traceEndCall类的afterCall方法,Spring容器就会根据配置文件在调用doSomething()方法前后自动调用相应的方法,通过在beforeCall()方法和afterCall()方法中添加跟踪的代码就可以满足对doSomething()方法调用的跟踪要求,同时还不需要更改原来已实现的代码模块。