面向方面编程(aspect-oriented prigraming, AOP)进一步完善了OOP, OOP的三个基本特性(封装,继承,多态)将应用程序的设计从类的内部和类的纵向关系考虑, 但是实际的应用程序还有一个复杂的问题没有在OOP中解决,那就是类之间在横向上的复杂交互关系, 在OOP中解决这个问题依靠的是设计模式. 但是设计模式并不是一个初学者容易掌握的技术. AOP在OOP的基础上又将程序分解成方面(aspect), 这使得我们可以模块化各个方面.方面在实际应用中比较常见的如日志,安全,事务管理等。
目前在java中实现AOP最获得认可的事aspectJ和spring AOP, aspectJ在java的语言中加入了多个新的语法成分,因而需要采取特殊的编译过程.而spring中没有改变java的语法,而是通过配置文件定义类之间的关系.从而不需要特殊的编译过程就可以实现面向方面的编程.
下面的例子演示了spring中AOP的运用,我们希望在连接点IBusinessLogic.foo()方法上采用MethodInterceptor,AfterReturningAdvice ,MethodBeforeAdvice, AroundAdvice,而在连接点IBusinessLogic.bar()上采用MethodInterceptor,AfterReturningAdvice ,MethodBeforeAdvice, AroundAdvice,ThrowsAdvice
定义业务
逻辑接口
package aop;
public interface IBusinessLogic {
public void foo();
public void bar() throws BusinessLogicException;
}
实现业务逻辑
package aop;
public class BusinessLogic implements IBusinessLogic {
public void foo() {
System.out.println("Inside BusinessLogic.foo()");
}
public void bar() throws BusinessLogicException {
System.out.println("Inside BusinessLogic.bar()");
throw new BusinessLogicException();
}
}
package aop;
import org.springframework.aop.ThrowsAdvice;
import java.lang.reflect.Method;
public class LoggingThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(Method method, Object[] args, Object target,
Throwable subclass) {
System.out.println("Logging that a " + subclass
+ " Exception was thrown.");
}
}
package aop;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class TracingAfterAdvice implements AfterReturningAdvice {
public void afterReturning(Object arg0, Method arg1, Object[] arg2,
Object arg3) throws Throwable {
System.out.println("Hello world! (by " + this.getClass().getName()
+ ")");
}
}
package aop;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class TracingAroundAdvice implements MethodInterceptor {
public Object invoke(MethodInvocation mi) throws Throwable {
System.out.println("Inside in TracingAroundAdvice:invoke()");
Object obj = mi.proceed();
System.out.println("Inside in TracingAroundAdvice:invoke()");
return obj;
}
}
package aop;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class TracingBeforeAdvice implements MethodBeforeAdvice {
public void before(Method arg0, Object[] arg1, Object arg2)
throws Throwable {
System.out.println("Hello world! (by " + this.getClass().getName()
+ ")");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!--business logic bean-->
<bean id="beanTarget" class="aop.BusinessLogic"></bean>
<!-- Advice classes -->
<bean id="theTracingBeforeAdvice" class="aop.TracingBeforeAdvice"/>
<bean id="theTracingAfterAdvice" class="aop.TracingAfterAdvice"/>
<bean id="theLoggingThrowsAdvice" class="aop.LoggingThrowsAdvice"/>
<bean id="theTracingAroundAdvice" class="aop.TracingAroundAdvice"/>
<!-- Advisor pointcut definition for before advice -->
<bean id="theTracingBeforeAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref local="theTracingBeforeAdvice"/>
</property>
<property name="pattern">
<value>.*</value>
</property>
</bean>
<!-- Advisor pointcut definition for before advice -->
<bean id="theTracingAfterAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref local="theTracingAfterAdvice"/>
</property>
<property name="pattern">
<value>.*</value>
</property>
</bean>
<!-- Advisor pointcut definition for around advice -->
<bean id="theTracingAroundAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref local="theTracingAroundAdvice"/>
</property>
<property name="pattern">
<value>.*</value>
</property>
</bean>
<bean id="theLoggingThrowsAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref local="theLoggingThrowsAdvice"/>
</property>
<property name="pattern">
<value>./IBusinessLogic/.foo</value>
</property>
</bean>
<bean id="businesslogicbean" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>aop.IBusinessLogic</value>
</property>
<property name="target">
<ref local="beanTarget"/>
</property>
<property name="interceptorNames">
<list>
<value>theTracingBeforeAdvisor</value>
<value>theTracingAfterAdvisor</value>
<value>theLoggingThrowsAdvice</value>
<value>theTracingAroundAdvisor</value>
</list>
</property>
</bean>
</beans>
package aop.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import aop.*;
public class MainApplication {
public static void main(String[] args) {
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
new String[] { "aop/aop.xml" });
IBusinessLogic testObject = (IBusinessLogic) appContext
.getBean("businesslogicbean");
testObject.foo();
try {
testObject.bar();
} catch (BusinessLogicException e) {
System.out.println("Caught BusinessLogicException");
}
}
}
运行结果:
Hello world! (by aop.TracingBeforeAdvice)
Inside in TracingAroundAdvice:invoke()
Inside BusinessLogic.foo()
Inside in TracingAroundAdvice:invoke()
Hello world! (by aop.TracingAfterAdvice)
Hello world! (by aop.TracingBeforeAdvice)
Inside in TracingAroundAdvice:invoke()
Inside BusinessLogic.bar()
Logging that a aop.BusinessLogicException Exception was thrown.
Caught BusinessLogicException