概念
术语
AspectJ
Jar包
-
实现AspectJ***
aopalliance-1.0.jar
aspectjweaver-1.6.8.jar
spring-aop-4.0.0.RELEASE.jar
<mark>spring-aspects-4.0.0.RELEASE.jar</mark>(没用到) -
实现spring创建类
spring-context-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
commons-logging-1.1.1.jar
spring-expression-4.0.0.RELEASE.jar
在配置文件中加入 aop 的命名空间
<!-- 设置要扫描的包 -->
<context:component-scan base-package="vedio.aop"> </context:component-scan>
- 使AspectJ注解起作用:自动为匹配的类生成***对象
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
基于注解的方式
-
把这个类声明为一个切面:需要把该类放入到IOC容器中,再声明为一个切面
@Aspect
@Component - 切面首先是一个 IOC 中的bean -
声明该方法时一个前置<mark>通知</mark>:在目标方法开始之前执行
@Before("executiong(public int 类全名.方法名(参数类型))")
@Before("execution(public int vedio.proxy.Calculator.*(int , int ) )")
所有(int, int )参数的方法
代码
<?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/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<!-- 设置要扫描的包 -->
<context:component-scan base-package="vedio.aop">
</context:component-scan>
<!-- 使AspectJ注解起作用:自动为匹配的类生成***对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
package vedio.aop;
import org.springframework.stereotype.Component;
import vedio.proxy.Calculator;
@Component("calculator")
public class CalculatorImp_aop implements Calculator{
@Override
public int add(int a, int b) {
return a+b;
}
@Override
public int sub(int a, int b) {
return a-b;
}
@Override
public int mul(int a, int b) {
return a*b;
}
@Override
public int div(int a, int b) {
return a/b;
}
}
package vedio.aop;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoginingAspect {
/** * 在方法执行之前执行的一段代码 */
@Before("execution(public int vedio.proxy.Calculator.*(..) )")
public void beforMethod( JoinPoint joinPoint ) {
//获取方法名
String methodName = joinPoint.getSignature().getName();
//获取参数
Object[] args = joinPoint.getArgs();
System.out.println("The method "+ methodName+Arrays.toString(args) + " begin");
}
//后置通知:在目标方法执行后(无论是否发生异常),执行的通知
//注意:这里不能获得结果,结果在返回其他通知里面
/** * 无论被***方法是否执行,之后一定执行! */
@After("execution(public int vedio.proxy.Calculator.*(..) )")
public void afterMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("The method "+ methodName+Arrays.toString(args) +" is end");
}
/** * 在方法正常结束时,执行的代码 * 返回通知时可以访问到方法的返回值的! */
@AfterReturning(value = "execution(public int vedio.proxy.Calculator.*(..) )" ,
returning = "result")
public void afterReturningMethod(JoinPoint jointPoint , Object result) {
String methodName = jointPoint.getSignature().getName();
Object[] args = jointPoint.getArgs();
System.out.println("The result of "+methodName+Arrays.toString(args)+" is " + result);
}
/** * 在目标方法出现异常时会执行的代码 * 可以访问到异常对象 * 且可以执行在出现特定异常时在执行通知代码 */
@AfterThrowing(value = "execution(public int vedio.proxy.Calculator.*(..) )" ,
throwing = "ex")
public void afterThrowingMethod(JoinPoint joinPoint , Exception ex) {
String methodName = joinPoint.getSignature().getName();
System.out.println("The method "+methodName+" occurs excetion:"+ex);
}
// /**
// * 环绕通知需要携带 ProceedingJoinPoint 类型的参数,
// * 环绕通知类似于动态***的全过程:
// * ProcedingJoinPoint 类型的参数可以决定是否执行目标的方法
// */
// @Around(value = "execution(public int vedio.proxy.Calculator.*(..) )")
// public Object aroundMthod(ProceedingJoinPoint pjd) {
// Object result = null ;
// String methodName = pjd.getSignature().getName();
// Object[] args = pjd.getArgs();
//
// //前置通知
// System.out.println("The method "+ methodName+Arrays.toString(args) + " begin");
//
// try {
// //执行目标方法
// result = pjd.proceed(args);
// //后置通知
// System.out.println("The method "+ methodName+Arrays.toString(args) +" is end");
// //返回通知
// System.out.println("The result of "+methodName+Arrays.toString(args)+" is " + result);
// } catch (Throwable e) {
// //后置通知
// System.out.println("The method "+ methodName+Arrays.toString(args) +" is end");
// //异常通知
// System.out.println("The method "+methodName+" occurs excetion:"+e);
// }finally {
// }
//
// return result;
// }
}
@Test
public void test01() {
ClassPathXmlApplicationContext pac =
new ClassPathXmlApplicationContext("vedio/beans-aop.xml");
Calculator c = pac.getBean("calculator" , Calculator.class);
int a = 4 ;
int b = 2 ;
int result =0 ;
result = c.add(a, b) ;
result = c.sub(a, b);
//异常
result = c.div(a, 0);
}
优先级
@Order(优先级)
<mark>值越小,优先级越高</mark>
/** * 在方法执行之前执行的一段代码 */
@Order(2)
@Before("execution(public int vedio.proxy.Calculator.*(..) )")
public void beforMethod( JoinPoint joinPoint ) {
//获取方法名
String methodName = joinPoint.getSignature().getName();
//获取参数
Object[] args = joinPoint.getArgs();
System.out.println("The method "+ methodName+Arrays.toString(args) + " begin");
}
@Aspect
@Component
public class ValidatingAspect {
@Order(1)
@Before("execution(public int vedio.proxy.Calculator.*(..))")
public void validatingArgs(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
//在执行之前
//判断args是否符合条件....
System.out.println(Arrays.toString(args)+" pass the validation of method "+ methodName);
}
}
重用切点表达式
/*
* 定义一个方法,用于声明切入点表达式,
* 使用 @Pointcut 来声明切入点表达式
* 后面的其他执行通知直接使用方法名来引用当前的切入点表达式。
*/
@Pointcut("execution(public int vedio.proxy.Calculator.*(..) )")
package vedio.aop;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class ValidatingAspect {
@Order(1)
@Before("vedio.aop.LoginingAspect.declareJoinPointExpression() ")
public void validatingArgs(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
//在执行之前
//判断args是否符合条件....
System.out.println(Arrays.toString(args)+" pass the validation of method "+ methodName);
}
}
package vedio.aop;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoginingAspect {
/* * 定义一个方法,用于声明切入点表达式, * 使用 @Pointcut 来声明切入点表达式 * 后面的其他执行通知直接使用方法名来引用当前的切入点表达式。 */
@Pointcut("execution(public int vedio.proxy.Calculator.*(..) )")
public void declareJoinPointExpression() {
//一般的,该方法中不再需要添加其他代码。
}
/** * 在方法执行之前执行的一段代码 */
@Order(2)
@Before("declareJoinPointExpression() ")
public void beforMethod( JoinPoint joinPoint ) {
//获取方法名
String methodName = joinPoint.getSignature().getName();
//获取参数
Object[] args = joinPoint.getArgs();
System.out.println("The method "+ methodName+Arrays.toString(args) + " begin");
}
//后置通知:在目标方法执行后(无论是否发生异常),执行的通知
//注意:这里不能获得结果,结果在返回其他通知里面
/** * 无论被***方法是否执行,之后一定执行! */
@After("declareJoinPointExpression() ")
public void afterMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("The method "+ methodName+Arrays.toString(args) +" is end");
}
/** * 在方法正常结束时,执行的代码 * 返回通知时可以访问到方法的返回值的! */
@AfterReturning(value ="declareJoinPointExpression() ",
returning = "result")
public void afterReturningMethod(JoinPoint jointPoint , Object result) {
String methodName = jointPoint.getSignature().getName();
Object[] args = jointPoint.getArgs();
System.out.println("The result of "+methodName+Arrays.toString(args)+" is " + result);
}
/** * 在目标方法出现异常时会执行的代码 * 可以访问到异常对象 * 且可以执行在出现特定异常时在执行通知代码 */
@AfterThrowing( value = "declareJoinPointExpression() " ,
throwing = "ex")
public void afterThrowingMethod(JoinPoint joinPoint , Exception ex) {
String methodName = joinPoint.getSignature().getName();
System.out.println("The method "+methodName+" occurs excetion:"+ex);
}
// /**
// * 环绕通知需要携带 ProceedingJoinPoint 类型的参数,
// * 环绕通知类似于动态***的全过程:
// * ProcedingJoinPoint 类型的参数可以决定是否执行目标的方法
// */
// @Around(value = "execution(public int vedio.proxy.Calculator.*(..) )")
// public Object aroundMthod(ProceedingJoinPoint pjd) {
// Object result = null ;
// String methodName = pjd.getSignature().getName();
// Object[] args = pjd.getArgs();
//
// //前置通知
// System.out.println("The method "+ methodName+Arrays.toString(args) + " begin");
//
// try {
// //执行目标方法
// result = pjd.proceed(args);
// //后置通知
// System.out.println("The method "+ methodName+Arrays.toString(args) +" is end");
// //返回通知
// System.out.println("The result of "+methodName+Arrays.toString(args)+" is " + result);
// } catch (Throwable e) {
// //后置通知
// System.out.println("The method "+ methodName+Arrays.toString(args) +" is end");
// //异常通知
// System.out.println("The method "+methodName+" occurs excetion:"+e);
// }finally {
// }
//
// return result;
// }
}
基于配置文件的方式
<?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" 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-4.0.xsd">
<!-- 配置bean -->
<bean id="calculator" class="vedio.aop.CalculatorImp_aop"></bean>
<!-- 配置切面bean -->
<bean id="loginingAspect" class="vedio.aop.LoginingAspect_xml"></bean>
<bean id="validatingAspect" class="vedio.aop.ValidatingAspect_xml"></bean>
<!-- 配置AOP -->
<aop:config >
<!-- 配置切点 - 表达式 -->
<aop:pointcut expression="execution(int vedio.proxy.Calculator.*(int ,int ))" id="calcPointcut" />
<!-- 配置切面、通知 -->
<aop:aspect order="1" ref="validatingAspect" >
<aop:before method="validatingArgs" pointcut-ref="calcPointcut" />
</aop:aspect>
<aop:aspect order="2" ref="loginingAspect">
<!-- 前置 -->
<aop:before method="beforMethod" pointcut-ref="calcPointcut"/>
<!-- 后置 -->
<aop:after method="afterMethod" pointcut-ref="calcPointcut"/>
<!-- 返回 -->
<aop:after-returning method="afterReturningMethod" pointcut-ref="calcPointcut" returning="result"/>
<!-- 异常 -->
<aop:after-throwing method="afterThrowingMethod" pointcut-ref="calcPointcut" throwing="ex"/>
<!-- 环绕 <aop:around method="aroundMethod" pointcut-ref=""/> -->
</aop:aspect>
</aop:config>
</beans>
package vedio.aop;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
public class ValidatingAspect_xml {
public void validatingArgs(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
//在执行之前
//判断args是否符合条件....
System.out.println(Arrays.toString(args)+" pass the validation of method "+ methodName);
}
}
package vedio.aop;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
public class LoginingAspect_xml {
public void beforMethod( JoinPoint joinPoint ) {
//获取方法名
String methodName = joinPoint.getSignature().getName();
//获取参数
Object[] args = joinPoint.getArgs();
System.out.println("The method "+ methodName+Arrays.toString(args) + " begin");
}
public void afterMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("The method "+ methodName+Arrays.toString(args) +" is end");
}
public void afterReturningMethod(JoinPoint jointPoint , Object result) {
String methodName = jointPoint.getSignature().getName();
Object[] args = jointPoint.getArgs();
System.out.println("The result of "+methodName+Arrays.toString(args)+" is " + result);
}
public void afterThrowingMethod(JoinPoint joinPoint , Exception ex) {
String methodName = joinPoint.getSignature().getName();
System.out.println("The method "+methodName+" occurs excetion:"+ex);
}
}
package video;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import vedio.proxy.Calculator;
public class Test_AOP_xml {
@Test
public void test01() {
ClassPathXmlApplicationContext pac =
new ClassPathXmlApplicationContext("vedio/beans-aop-xml.xml");
Calculator c = pac.getBean("calculator" , Calculator.class);
int a = 4 ;
int b = 2 ;
int result ;
result = c.add(a, b) ;
result = c.sub(a, b);
result = c.div(a, 0);
}
}