Spring(三):注解式AOP的使用

  Spring 支持 AspectJ的注解式切面编程。AOP可以让一组类共享相同的行为。

注解

  1. 使用@Aspect声明一个切面。
  2. 使用@After,@Before,@Around定义建言(Advice),可以直接拦截规则(切点)作为参数。
  3. 其中**@After,@Before,@Around参数的拦截规则为切点(PointCut),为了使切点复用,可使用@PointCut专门定义拦截规则,然后在@After,@Before,@Around**的参数中调用。
  4. 其中符合条件的每一个被拦截处为连接点(JoinPoint)。

示例

  1. 编写拦截规则的注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.aop;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Action {
String name();
}
  1. 编写使用注解的被拦截的类
1
2
3
4
5
6
7
8
9
10
11
12
package com.aop;

import org.springframework.stereotype.Service;

@Service
public class DemoAnnotationService {
@Action(name="注解释拦截的add操作")
public void add() {
System.out.println("DemoAnnotationService ---");

}
}
  1. 编写使用方法规则的被拦截的类
1
2
3
4
5
6
7
8
9
10
11
12
package com.aop;

import org.springframework.stereotype.Service;

@Service
public class DemoMethodService {

public void add() {
System.out.println("DemoMethodService ---");
}

}
  1. 编写切点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.aop;

import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

@Aspect //声明一个切面
@Component //成为spring容器中的一个Bean
public class LogAspect {

@Pointcut("@annotation(com.aop.Action)")//声明切点
public void annotationPointCut() {};

@After("annotationPointCut()") //声明建言,并使用@Pointcut定义切点
public void after(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Action action = method.getAnnotation(Action.class);
System.out.println("注解式拦截,在方法执行之后拦截: " + action.name());//通过反射获取注解上的属性
}

@Before("execution(* com.aop.DemoMethodService.*(..))")
public void before(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
System.out.println("方法规则式拦截,方法执行之前拦截:" + method.getName());
}

}
  1. 编写配置类
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.aop;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan("com.aop")
@EnableAspectJAutoProxy//开启spring对AspectJ的支持
public class AopConfig {

}

  1. 运行测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.aop;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AopMain {

public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class);

DemoAnnotationService demoAnnotationService = context.getBean(DemoAnnotationService.class);
DemoMethodService demoMethodService = context.getBean(DemoMethodService.class);

demoAnnotationService.add();
demoMethodService.add();

context.close();
}
}
  1. 运行结果
1
2
3
4
DemoAnnotationService ---
注解式拦截,在方法执行之后拦截: 注解释拦截的add操作
方法规则式拦截,方法执行之前拦截:add
DemoMethodService ---
作者

光星

发布于

2018-02-27

更新于

2022-06-17

许可协议

评论