Spring AOP和自定义注解

喜欢ヅ旅行 2022-06-12 06:29 348阅读 0赞

用过Spring的朋友都知道,Spring有两大核心功能,一个是IOC,一个是AOP。IOC对于开发者来讲可能用的还比较多,声明一个Bean交给Spring容器来管理,或者从Spring容器中找到某个Bean注入到另一个Bean中。而对于AOP来讲,普通开发者用的就不是很多了。往往是项目的整体架构都已经对切面进行处理完毕了,记录日志也好,处理数据库事务也好等等这些功能,程序员一般是不需要关注的,当然这也是AOP的核心—关注点分离。这篇笔记并不是来记录如何使用AOP的,对于AOP的讲解网络上有很多的文章,可以参考。这里主要介绍的是使用Java配置的方式实现AOP,以及使用自定义注解

用一个实际的例子来演示使用注解和使用单纯的AOP的方式来面向切面编程。主要目标是实现在某个方法上打上我们自定义的注解,就可以被切面所拦截,在方法执行前或者方法执行后执行一些操作。

我们这里需要一个注解类,两个服务提供者,一个切面,再加一个配置类和一个运行的类,运行的类并充当服务的消费者。

注解类

  1. @Target(ElementType.METHOD)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface Action {
  5. String name();
  6. }

这里定义了一个注解,表示是运行时生效,目标是标注在方法上。可以指定一个name属性。注解本身就是一个标记,是没有任何的功能的。

第一个服务的提供者,不使用注解

  1. @Service
  2. public class DemoService {
  3. public void add() {
  4. }
  5. }

这里就提供了一个空的add方法

第二个服务的提供者,使用注解

  1. @Service
  2. public class DemoAnnotationService {
  3. @Action(name="注解拦截的add操作")
  4. public void add() {
  5. }
  6. }

这里和第一个服务的提供者类似,同样提供了一个空的add方法,只是在add方法上标注了我们定义的action注解,并指定了name属性的值

切面

  1. @Aspect // 声明一个切面
  2. @Component
  3. public class LogAspect {
  4. // 关于切入点,可以单独定义,如下。也可以直接写在通知中。单独定义的可以复用,而写到通知中的不可以进行复用。类似于函数和匿名函数。
  5. @Pointcut("@annotation(com.hy.spring.test3.Action)") // 定义一个切入点
  6. public void annotationPointCut() {}
  7. @Before("execution(* com.hy.spring.test3.DemoService.*(..))") // 定义一个前置通知,并制定切入点表达式
  8. public void begin(JoinPoint joinPoint) {
  9. MethodSignature signature = (MethodSignature) joinPoint.getSignature();
  10. Method method = signature.getMethod();
  11. System.out.println("方法规则式拦截 " + method.getName());
  12. }
  13. @After("annotationPointCut()") // 声明一个后置通知,并使用之前定义的切入点
  14. public void after (JoinPoint joinPoint) {
  15. MethodSignature signature = (MethodSignature) joinPoint.getSignature();
  16. Method method = signature.getMethod();
  17. Action action = method.getAnnotation(Action.class);
  18. System.out.println("注解式拦截 " + action.name());
  19. }
  20. }

这个是我们的核心代码,先看注解,这里用到了Aspect,Component,Pointcut,Before,After。分别介绍这5个注解
























Aspect

声明一个切面

Pointcut

声明切点

Before

声明前置通知

After

声明后置通知

Component

交给spring容器来管理

了解了注解的基本功能之后,再来对代码进行分析。如果对AOP不熟悉的小伙伴可以先了解一下AOP的相关内容,再来继续向下学习。这里其实就是两个通知,一个前置通知,一个后置通知,分别对应这两个切入点。切入点的配置方式有两种,第一种就是在前置通知中定义的形式,直接将切面表达式写到注解中,另外可以单独将切入点定义处理,并使用Pointcut来声明这个切入点表达式,方法的名字就是切点的名称。后置通知中就是使用的这种形式,在后置通知的注解中指定切点的方法名,这里一定要把方法的()加上,否则找不到切点。切点表达式定义的都非常简单,annotationPointCut()切点就是要切带有com.hy.spring.test3.Action这个注解的所有类, @Before(“execution(* com.hy.spring.test3.DemoService.*(..))”)要切的就是com.hy.spring.test3.DemoService这个包下的所有类。下面我们再来看切了之后干的啥事,不难发现,做的事情也是非常的简单,带有注解的就是打印了注解中配置的值,没有注解的就打印了方法的名字。

配置类

  1. @Configuration
  2. @ComponentScan(value= "com.hy.spring.test3")
  3. @EnableAspectJAutoProxy // 这里很关键,必须要开启对AOP的支持
  4. public class AopConfig {
  5. }

ComponentScan是要扫描的包,这个注解会自动扫描指定包下的所有的类

EnableAspectJAutoProxy是开启切面的自动代理

测试类

  1. public class Main {
  2. public static void main(String[] args) {
  3. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class);
  4. DemoAnnotationService service = context.getBean(DemoAnnotationService.class);
  5. service.add();
  6. context.close();
  7. }
  8. }

这里只演示了注解的切面,非注解的同样。

发表评论

表情:
评论列表 (有 0 条评论,348人围观)

还没有评论,来说两句吧...

相关阅读

    相关 aop实现定义注解

    注解简单知识 关键字 自定义注解的关键字是@interface 参数类型 自定义注解的参数类型:八大基础类型、String、枚举、注解,还可以是以上类型对应