基于xml与基于注解的AOP本质上是非常相似的,都是需要封装横切关注点,封装到切面中,然后把横切关注点封装为一个方法,再把该方法设置为当前的一个通知,再通过切入点表达式定位到横切点就可以了,思路是非常相似的。
我们的接口代码如下所示:
package com.rgf.spring.aop.annotation.xml;
import org.springframework.stereotype.Component;
@Component
public interface Calculator {
int add(int i,int j);
int sub(int i,int j);
int mul(int i,int j);
int div(int i,int j);
}
我们的实现类如下所示:
package com.rgf.spring.aop.annotation.xml;
import org.springframework.stereotype.Component;
/**
*
*/
@Component
public class CalculatorImpl implements Calculator {
@Override
public int add(int i, int j) {
int result=i+j;
System.out.println("方法内部,result:"+result);
return result;
}
@Override
public int sub(int i, int j) {
int result=i-j;
System.out.println("方法内部,result:"+result);
return result;
}
@Override
public int mul(int i, int j) {
int result=i*j;
System.out.println("方法内部,result:"+result);
return result;
}
@Override
public int div(int i, int j) {
int result=i/j;
System.out.println("方法内部,result:"+result);
return result;
}
}
我们封装的切面方法如下所示:
package com.rgf.spring.aop.annotation.xml;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
public class LoggerAspect {
public void beforeAdviceMethod(JoinPoint joinPoint){
Signature signature = joinPoint.getSignature();
Object[] args = joinPoint.getArgs();
System.out.println("LoggerAspect,方法:"+signature.getName()+",参数:"+ Arrays.toString(args));
}
public void afterAdviceMethod(JoinPoint joinPoint){
Signature signature = joinPoint.getSignature();
Object[] args = joinPoint.getArgs();
System.out.println("LoggerAspect,方法:"+signature.getName()+",执行完毕");
}
public void afterReturningAdviceMethod(JoinPoint joinPoint,Object result){
Signature signature = joinPoint.getSignature();
Object[] args = joinPoint.getArgs();
System.out.println("LoggerAspect,方法:"+signature.getName()+",结果:"+result);
}
public void afterThrowingAdviceMethod(JoinPoint joinPoint,Throwable ex){
Signature signature = joinPoint.getSignature();
System.out.println("LoggerAspect,方法:"+signature.getName()+",异常:"+ex);
}
public Object aroundAdviceMethod(ProceedingJoinPoint joinPoint){
Object result=null;
try {
System.out.println("环绕通知-->前置通知");
//表示目标对象方法的执行
result = joinPoint.proceed();
System.out.println("环绕通知-->返回通知");
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("环绕通知-->异常通知");
}finally {
System.out.println("环绕通知-->后置通知");
}
return result;
}
}
我们封装的切面如下所示:
package com.rgf.spring.aop.annotation.xml;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* 切面的优先级:
* 可以通过@Order注解的value属性设置优先级,默认值Integer的最大值
* @Order注解的value属性值越小,优先级越高
*
*/
@Component
public class ValidateAspect {
public void beforeMethod(){
System.out.println("ValidateAspect-->前置通知");
}
}
我们的配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--扫描组件-->
<context:component-scan base-package="com.rgf.spring.aop.annotation.xml"></context:component-scan>
<!-- <cop:aspectj-autoproxy:开启基于注解的aop-->
<aop:config>
<!--设置一个公共的切入点表达式-->
<aop:pointcut id="pointcut" expression="execution(* com.rgf.spring.aop.annotation.xml.CalculatorImpl.*(..))"/>
<!--aop:aspect:将IOC容器中的某个bean(某个组件)设置为切面,通过ref引用某一个besn的id,就可以将当前这一个bean来设置为一个切面-->
<!--aop:advisor:设置当前的通知-->
<!--aop:pointcut:设置切入点表达式-->
<aop:aspect ref="loggerAspect">
<aop:before method="beforeAdviceMethod" pointcut-ref="pointcut"></aop:before>
<aop:after method="afterAdviceMethod" pointcut-ref="pointcut"></aop:after>
<aop:after-returning method="afterReturningAdviceMethod" returning="result" pointcut-ref="pointcut"></aop:after-returning>
<aop:after-throwing method="afterThrowingAdviceMethod" throwing="ex" pointcut-ref="pointcut"></aop:after-throwing>
<aop:around method="aroundAdviceMethod" pointcut-ref="pointcut"></aop:around>
</aop:aspect>
<!--order进行设置他的优先级.设置的值越小,优先级越高-->
<aop:aspect ref="validateAspect" order="1">
<aop:before method="beforeMethod" pointcut-ref="pointcut"></aop:before>
</aop:aspect>
</aop:config>
</beans>
我们进行测试如下所示:
package com.rgf.spring.test;
import com.rgf.spring.aop.annotation.xml.Calculator;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AOPByXMLTest {
@Test
public void testAOPByXML(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("aop-xml.xml");
Calculator calculator = ioc.getBean(Calculator.class);
calculator.add(1,1);
}
}
我们进行运行之后如下所示: