基于XML方式的切面实现
若干AspectJ标签的含义
- <aop:config>:配置AOP,实现将一个普通类设置为切面类的功能
- <aop:aspect>:配置切面
- <aop:pointcut>:配置切点
- <aop:before>:配置前置通知,将一个切面方法设置为前置增强
- <aop:after-returning>:配置后置通知,将一个切面方法设置为后置通知,有返回值
- <aop:around>:配置环绕通知
- <aop:after-throwing>:配置异常通知,将一个切面设置为异常抛出增强
- <aop:after>:配置最终通知,将一个切面方法设置为后置增强,没有有返回值,无论是否异常都执行
execution()
表达式
execution()
表达式是切点表达式中最常用的方法之一,用于匹配方法执行连接点。它的语法如下
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
其中,各个部分的含义如下:
modifiers-pattern
:可选项,用于匹配方法的修饰符(如public
、private
等)。可以使用通配符*
表示任意修饰符。ret-type-pattern
:用于匹配方法的返回类型。可以使用通配符*
表示任意类型。declaring-type-pattern
:可选项,用于匹配方法所在的类或接口。可以使用通配符*
表示任意类型。name-pattern
:用于匹配方法名。可以使用通配符*
表示任意字符,或使用..
表示任意多个字符。param-pattern
:可选项,用于匹配方法的参数类型。可以使用通配符*
表示任意类型,或使用..
表示任意多个参数。throws-pattern
:可选项,用于匹配方法抛出的异常类型。可以使用通配符*
表示任意异常类型。
下面是一些 execution()
表达式的案例:
execution(public void com.example.MyClass.doSomething())
:匹配com.example.MyClass
类中的doSomething()
方法,且返回类型为void
,修饰符为public
。execution(* com.example.*.*())
:匹配com.example
包下的所有类的无参方法。execution(* com.example.MyClass.*(String, *))
:匹配com.example.MyClass
类中接受一个String
类型参数和任意类型参数的方法。execution(* com.example..*.*())
:匹配com.example
包及其子包下的所有类的无参方法。execution(public * com.example.MyInterface+.*(..))
:匹配实现了com.example.MyInterface
接口的类的任意公共方法。
这些示例展示了不同的 execution()
表达式用法,可以根据具体需求灵活组合使用各个部分来定义切入点。
案例分析
以下是使用XML配置方式实现切面的案例代码:
1. 创建目标类 `MyClass.java`:
public class MyClass {
public void doSomething() {
System.out.println("Doing something...");
}
}
2. 创建切面类 `MyAspect.java`:
public class MyAspect {
public void beforeAdvice() {
System.out.println("Before advice executed");
}
}
3. 创建Spring配置文件 `spring-config.xml`:
<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.xsd">
<!-- 配置目标对象 -->
<bean id="myClass" class="com.example.MyClass"/>
<!-- 配置切面对象 -->
<bean id="myAspect" class="com.example.MyAspect"/>
<!-- 配置切面 -->
<aop:config>
<!-- 配置切入点表达式 -->
<aop:pointcut id="myPointcut" expression="execution(* com.example.MyClass.doSomething())"/>
<!-- 配置通知 -->
<aop:aspect ref="myAspect">
<!-- 配置前置通知 -->
<aop:before method="beforeAdvice" pointcut-ref="myPointcut"/>
</aop:aspect>
</aop:config>
</beans>
在上面的配置文件中,我们首先定义了目标对象 `myClass` 和切面对象 `myAspect`。然后,使用 `<aop:config>` 配置元素定义切面。在切面中,我们使用 `<aop:pointcut>` 定义切入点表达式,该表达式指定了要拦截的方法。然后,使用 `<aop:before>` 配置元素定义前置通知,将前置通知与切入点关联起来。
4. 创建测试类 `Main.java`:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.example.MyClass;
public class Main {
public static void main(String[] args) {
// 加载Spring配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 获取代理对象
MyClass myClass = (MyClass) context.getBean("myClass");
// 调用目标方法
myClass.doSomething();
}
}
在上面的测试类中,我们通过加载Spring配置文件来初始化Spring容器。然后,从容器中获取代理对象 `myClass`,并调用目标方法 `doSomething()`。
当运行测试类时,前置通知 `beforeAdvice()` 将会在目标方法执行前被调用。
这是一个使用XML配置方式实现切面的简单案例。通过定义切入点和通知,我们可以在目标方法执行前后添加额外的逻辑。