前面两个文章介绍了Aop及其相关重要概念,下面主要用代码的方式介绍下实现Spring Aop的几种方式
1. 基于注解实现Spring Aop
业务类接口
package cn.test.business;
public interface Work {
public void doWork(String userName);
}
业务类实现
package cn.test.business;
public class Worker implements Work{
@Override
public void doWork(String userName) {
System.out.println(userName + " is working !");
}
}
@Aspect
public class AopAnnotationTest {
@Pointcut("execution(* cn.test.business.*.*(..))")
private void anyMethod(){}//定义一个切入点
@Before("anyMethod() && args(name)")
public void doBefore(String name){
System.out.println("doBefore...");
}
@AfterReturning("anyMethod()")
public void doAfterReturning(){
System.out.println("doAfterReturning...");
}
@After("anyMethod()")
public void doAfter(){
System.out.println("doAfter...");
}
@Around("anyMethod()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("begin doAround...");
Object object = joinPoint.proceed();
System.out.println("after doAround...");
return object;
}
@AfterThrowing("anyMethod()")
public void doThrow(){
System.out.println("意外通知");
}
}
spring配置文件:spring-aop.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<bean id="work" class="cn.test.business.Worker"></bean>
<!-- aop注解 实现 -->
<aop:aspectj-autoproxy/>
<bean id="anno-beforeadvice" class="cn.test.aop.advice.annoation.impl.AopAnnotationTest"/>
<!-- 实现相应的Advice方法实现aop -->
<!-- <bean id="logBeforeAdvice" class="cn.test.aop.advice.inteface.impl.LogBeforeAdvice"></bean>
<bean id="logAfterReturnAdvice" class="cn.test.aop.advice.inteface.impl.LogAfterReturnAdvice"></bean>
<bean id="logExceptionAdvice" class="cn.test.aop.advice.inteface.impl.LogExceptionAdvice"></bean>
<bean id="logAroundAdvice" class="cn.test.aop.advice.inteface.impl.LogAroundAdvice"></bean>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* cn.test.business.*.*(..))" />
<aop:advisor advice-ref="logBeforeAdvice" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="logAfterReturnAdvice" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="logAroundAdvice" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="logExceptionAdvice" pointcut-ref="pointcut"/>
</aop:config> -->
<!-- 定义一个切面类 -->
<!-- <bean id="logAspect" class="cn.test.aop.advice.defineAspectClass.impl.TestAspect"></bean>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* cn.test.business.*.*(..))" />
<aop:aspect id="aspect" ref="logAspect">
<aop:before pointcut-ref="pointcut" method="doBefore"/>
<aop:after-returning pointcut-ref="pointcut" method="afterReturning" returning="retValue"/>
<aop:after-throwing pointcut-ref="pointcut" method="doThrowing" throwing="ex"/>
<aop:after pointcut-ref="pointcut" method="doAfter"/>
<aop:around pointcut-ref="pointcut" method="doAround"/>
</aop:aspect>
</aop:config> -->
</beans>
测试类:
package cn.test.aop.test;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import cn.test.business.Work;
@ContextConfiguration(
locations={
"classpath:/spring-aop.xml"
}
)
public class SpringAopTest extends AbstractJUnit4SpringContextTests{
@Autowired
private Work work;
@Test
public void aopTest(){
work.doWork("张三");
}
}
测试结果:
begin doAround...
doBefore...
张三 is working !
after doAround...
doAfter...
doAfterReturning...
2. 实现Adivce接口的方式实现Spring Aop
定义前置通知
public class LogBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target)
throws Throwable {
System.out.println(args[0] + "开始工作!");
}
}
定义环绕通知
public class LogAroundAdvice implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
System.out.println(arg0.getArguments()[0] + " 工作中,请勿打扰...");
Object obj = arg0.proceed();
System.out.println(arg0.getArguments()[0] + " 工作完成...");
return obj;
}
}
定义返回后通知
public class LogAfterReturnAdvice implements AfterReturningAdvice{
@Override
public void afterReturning(Object returnValue, Method method,
Object[] args, Object target) throws Throwable {
System.out.println(args[0] + "完成工作");
}
}
定义抛出异常后通知
public class LogExceptionAdvice implements ThrowsAdvice{
public void afterThrowing(Method method, Object[] parameters, Object target, Exception ex){
System.out.println(parameters[0] + " 工作中出现异常... ");
}
}
spring配置文件:只需要把上面的配置文件中第二部分打开即可。
<!-- 实现相应的Advice方法实现aop -->
<bean id="logBeforeAdvice" class="cn.test.aop.advice.inteface.impl.LogBeforeAdvice"></bean>
<bean id="logAfterReturnAdvice" class="cn.test.aop.advice.inteface.impl.LogAfterReturnAdvice"></bean>
<bean id="logExceptionAdvice" class="cn.test.aop.advice.inteface.impl.LogExceptionAdvice"></bean>
<bean id="logAroundAdvice" class="cn.test.aop.advice.inteface.impl.LogAroundAdvice"></bean>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* cn.test.business.*.*(..))" />
<aop:advisor advice-ref="logBeforeAdvice" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="logAfterReturnAdvice" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="logAroundAdvice" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="logExceptionAdvice" pointcut-ref="pointcut"/>
</aop:config>
3. 定义切面类的方式实现Spring Aop
切面类
public class TestAspect {
public void doAfter(JoinPoint jp) {
System.out.println(jp.getArgs()[0] + " 回家...");
}
public void afterReturning (JoinPoint joinPoint, Object retValue) {
System.out.println(joinPoint.getArgs()[0] + " 结束工作...");
}
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
long time = System.currentTimeMillis();
Object retVal = pjp.proceed();
time = System.currentTimeMillis() - time;
System.out.println(pjp.getArgs()[0] +" 工作时间: " + time + " ms");
return retVal;
}
public void doBefore(JoinPoint jp) {
System.out.println(jp.getArgs()[0] + " 开始工作...");
}
public void doThrowing(JoinPoint jp, Throwable ex) {
System.out.println(jp.getArgs()[0] + " 工作中出现异常... " + ex);
}
}
spring配置文件:
<bean id="logAspect" class="cn.test.aop.advice.defineAspectClass.impl.TestAspect"></bean>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* cn.test.business.*.*(..))" />
<aop:aspect id="aspect" ref="logAspect">
<aop:before pointcut-ref="pointcut" method="doBefore"/>
<aop:after-returning pointcut-ref="pointcut" method="afterReturning" returning="retValue"/>
<aop:after-throwing pointcut-ref="pointcut" method="doThrowing" throwing="ex"/>
<aop:after pointcut-ref="pointcut" method="doAfter"/>
<aop:around pointcut-ref="pointcut" method="doAround"/>
</aop:aspect>
</aop:config>