在编写 AspectJ 切面时, 可以直接在通知注解中书写切入点表达式. 但同一个切点表达式可能会在多个通知中重复出现.
在 AspectJ 切面中, 可以通过 @Pointcut 注解将一个切入点声明成简单的方法. 切入点的方法体通常是空的, 因为将切入点定义与应用程序逻辑混在一起是不合理的.
切入点方法的访问控制符同时也控制着这个切入点的可见性. 如果切入点要在多个切面中共用, 最好将它们集中在一个公共的类中. 在这种情况下, 它们必须被声明为 public. 在引入这个切入点时, 必须将类名也包括在内. 如果类没有与这个切面放在同一个包中, 还必须包含包名.
其他通知可以通过方法名称引入该切入点.
好吧,我们之前提过连接点、切点的定义。现在还能分清吗?如果这里需要做个分辨,那么你可以将切点理解为切点表达式,连接点为各个通知的JointPoint参数。
我们看两个切面的定义,其中一个切面的类方法中有一个方法用于声明切点表达式,这样该切点类的其他通知都可以使用这个方法来注解各个通知的切点表达式;其他切点的通知也可以只用,但要写清类名。
package com.happBKs.spring.aopbasic.aop1;
import java.util.Arrays;
import java.util.List;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
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;
@Order(Integer.MAX_VALUE)
@Aspect
@Component
public class DataValidateAspect {
/*
* 定义一个方法用于声明切点表达式。一般的,该方法中再也不需要添加其他代码
* 使用@Pointcut注解声明切点表达式
*/
@Pointcut("execution(public int com.happBKs.spring.aopbasic.aop1.AtithmeticCalculate.*(..))")
public void declarePointCut(){}
@Before("declarePointCut()")
public boolean beforeMethod(JoinPoint joinPoint)
{
String methodName=joinPoint.getSignature().getName();
List<Object> args=Arrays.asList(joinPoint.getArgs());
System.out.println("data validate---begin to "+methodName+" with "+args);
if((Integer)(args.get(0))>0&&(Integer)(args.get(1))>0)
{
System.out.println("data is OK");
return true;
}
else
{
System.out.println("data is bad");
return false;
}
}
}
package com.happBKs.spring.aopbasic.aop1;
import java.util.Arrays;
import java.util.List;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
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 DataValidateAspect2 {
@Before("com.happBKs.spring.aopbasic.aop1.DataValidateAspect.declarePointCut()")
public boolean beforeMethod(JoinPoint joinPoint)
{
String methodName=joinPoint.getSignature().getName();
List<Object> args=Arrays.asList(joinPoint.getArgs());
System.out.println("data validate 2---begin to "+methodName+" with "+args);
if((Integer)(args.get(0))<10000&&(Integer)(args.get(1))<10000)
{
System.out.println("data is OK");
return true;
}
else
{
System.out.println("data is bad");
return false;
}
}
}
配置文件:
<?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-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<context:component-scan base-package="com.happBKs.spring.aopbasic.aop1"></context:component-scan>
<!-- 使用AspectJ注解起作用。自动为匹配的类生成代理对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
测试代码:
@Test
public void testSpringAOP()
{
//1. 创建spring 的 IOC 容器
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
//2. 从IOC容器获取bean实例
AtithmeticCalculate atithmeticCalculate = (AtithmeticCalculate)ac.getBean(AtithmeticCalculate.class);
//考察一下代理对象是否生成
System.out.println(atithmeticCalculate.getClass().getName());
//3. 使用bean
System.out.println("Example 1:");
int result=atithmeticCalculate.add(10, 5);
System.out.println(result);
// System.out.println("\r\nExample 2:");
// int result2=atithmeticCalculate.div(10, 0);
// System.out.println(result2);
}
输出结果:
com.sun.proxy.$Proxy10
Example 1:
data validate---begin to add with [10, 5]
data is OK
data validate 2---begin to add with [10, 5]
data is OK
15