首先我们先创建一个接口类,写一个简单易懂的例子,比如,实现加减乘除的接口,然后我们通过该接口来实现基于注解的切面实现。
package com.text2;
public interface C1 {
public int jia(int a, int b);
public int jian(int a, int b);
public int chen(int a, int b);
public int chu(int a, int b);
}
下面是接口的实现类:
package com.text2;
import org.springframework.stereotype.Component;
@Component(“C1”)/声明改类为Spring管理的/
public class C1Impl implements C1 {
public C1Impl() {
System.out.println(“C1Impl构造器”);
}
public int jia(int a, int b) {
return a+b;
}
public int jian(int a, int b) {
return a-b;
}
public int chen(int a, int b) {
return a*b;
}
public int chu(int a, int b) {
return a/b;
}
}
下面我们实现切面:
package com.text2;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
/**
* 将该类声明为一个切面:需要把该类放入到IOC容器中,再声明为一个切面 @aspect
* 使用Order声明切面的优先级,值越小优先级越高
*/
@Order(1)
@Aspect/*声明为切面*/
@Component/*声明为spring管理的组件*/
public class C2 {
/**
* 定义一个方法,用于声明切入点表达式,该方法中不需要添入其他的代码
* 使用@Pointcut来声明切入点表达式
* 后面的其他通知直接使用方法名来引入切入点表达式
*/
@Pointcut("execution(* com.text2.C1.*(..))")
public void declareJointPointExpression(){}
/**
* 声明该方法是一个前置通知,
* 在目标方法开始之前执行
* @param joinPoint
*/
@Before("declareJointPointExpression()")
public void beforeMethod(JoinPoint joinPoint){
//得到方法的名字
String name = joinPoint.getSignature().getName();
//得到方法的参数
List<Object> list = Arrays.asList(joinPoint.getArgs());
System.out.println("The beforeMethod :"+name+list);
}
/**
* 声明该方法是一个后置通知,在连接点返回结果或者抛出异常的时候,
* 下面的后置通知记录了方法的终止,
* 在后置通知中还不能访问目标方法执行的结果
* @param joinPoint
*/
@After("declareJointPointExpression()")
public void afterMethod(JoinPoint joinPoint){
//得到方法的名字
String name = joinPoint.getSignature().getName();
//得到方法的参数
List<Object> list = Arrays.asList(joinPoint.getArgs());
System.out.println("The afterMethod :"+name+list);
}
/**
* 返回通知,返回通知是可以访问到方法的返回值的
* @param joinPoint
* @param result
*/
@AfterReturning(value = "declareJointPointExpression()",returning = "result")
public void afterReturning(JoinPoint joinPoint,Object result){
String name = joinPoint.getSignature().getName();
System.out.println("The afterReturning "+name+" ends with "+ result.toString());
}
/**
* 异常通知,在目标方法出现异常时会执行的代码,
* 可以访问到异常对象;且可以指定在出现特定异常时在执行通知代码
* @param joinPoint
* @param ex
*/
@AfterThrowing(value = "declareJointPointExpression()",throwing = "ex")
public void afterThrowing(JoinPoint joinPoint,Exception ex){
String name = joinPoint.getSignature().getName();
System.out.println("The afterThrowing "+name+" ends with "+ ex.toString());
}
/**
* 环绕通知:跟动态代理一样,需要携带ProceedingJoinPoint类型的参数
* 环绕通知类似于动态代理的全过程ProceedingJoinPoint类型的参数可以决定是否执行目标
* 且必须有返回值,返回值为目标方法的返回值
* @param proceedingJoinPoint
* @return
*/
@Around(value = "declareJointPointExpression()")
public Object aroundMethod(ProceedingJoinPoint proceedingJoinPoint){
Object o = null;
String methodName = proceedingJoinPoint.getSignature().getName();
//执行目标方法
try {
//前置通知
System.out.println("The aroundMethod "+methodName+" begins with "+ Arrays.asList(proceedingJoinPoint.getArgs()));
o = proceedingJoinPoint.proceed();
//返回通知
System.out.println("The aroundMethod "+ methodName +" ends with "+ o);
} catch (Throwable throwable) {
throwable.printStackTrace();
//异常通知
System.out.println("The aroundMethod "+ methodName +" occurs exception: "+ throwable);
}
//后置通知
System.out.println("The aroundMethod "+ methodName+" ends");
return o;
}
}
测试类:
package com.text2;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import static org.junit.Assert.*;
public class TestC {
@org.junit.Test
public void b1() throws Exception {
/*创建Spring的IOC容器*/
ApplicationContext ctx = new ClassPathXmlApplicationContext("text2.xml");
/*从IOC中获取bean的实例*/
C1 c1 = (C1) ctx.getBean("C1");
int result = c1.chu(10,2);
System.out.println("值:"+result);
}
}
XML配置文件
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--可以设置包含与不包含那些包下的与类,接口-->
<context:component-scan base-package="com.text2"></context:component-scan>
<!--使AspjectJ注解起作用:自动为匹配的对象生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>