Spring 支持 AspectJ的注解式切面编程。AOP可以让一组类共享相同的行为。
注解
- 使用
@Aspect
声明一个切面。
- 使用
@After,@Before,@Around
定义建言(Advice
),可以直接拦截规则(切点)作为参数。
- 其中**@After,@Before,@Around参数的拦截规则为切点(PointCut),为了使切点复用,可使用
@PointCut
专门定义拦截规则,然后在@After,@Before,@Around**的参数中调用。
- 其中符合条件的每一个被拦截处为连接点(
JoinPoint
)。
示例
- 编写拦截规则的注解
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 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 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 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 public class LogAspect { @Pointcut("@annotation(com.aop.Action)") public void annotationPointCut() {}; @After("annotationPointCut()") 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 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 public class AopConfig { }
|
- 运行测试
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 2 3 4
| DemoAnnotationService --- 注解式拦截,在方法执行之后拦截: 注解释拦截的add操作 方法规则式拦截,方法执行之前拦截:add DemoMethodService ---
|