基于Spring AOP实现注解功能(示例、原理及无效情况说明)

本文介绍了如何使用Spring AOP和注解实现方法增强,包括定义注解、切面及增强逻辑,以及详细解释了实现原理。同时,文章列举并分析了配置错误、无效用法的情况,如配置遗漏、表达式错误以及代理对象的调用问题,帮助读者避免常见的陷阱。
摘要由CSDN通过智能技术生成

1,正确示例

示例中通过注解增强被注解方法功能:数据保存到本地 db 时,同时将该数据封装成统一的消息格式发送到 kafka

1.1 定义注解

package com.demo;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)//方法注解(非构造方法)
@Retention(RetentionPolicy.RUNTIME)//运行时有效
@Inherited//使注解可以被子类继承,但如果子类@Override覆写了被注解方法则无效
public @interface DbInsertAnnotation {
    // 无参数
}

1.2 定义切面,并实现增强逻辑

package com.demo;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
@Component
public class DbAspect
{    

    @Pointcut("execution(@com.demo.DbInsertAnnotation * *(..))")//切面
    public void pointcut()
    {
    }
    
    @Around("pointcut()")
    public void around(ProceedingJoinPoint pjp) throws Throwable {
        //方法本身功能,写入db
        pjp.proceed();
        
        //增强的功能,发送消息到kafka
        sendMsg2Kafka(getMessageFromPjp(pjp));
    }
    
    private Object getMessageFromPjp(ProceedingJoinPoint pjp) {
        //TODO
    }
}

1.3 使用注解

package com.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class Demo
{
    @Autowired
    TestDAO testDAO;
    
    @DbInsert
    public void insertDb(Object obj) {
        testDAO.insert(obj);
    }
}

1.4 调用被注解增强的方法

package com.demo;

import org.springframework.beans.factory.annotation.Autowired;

public class UseDemo
{
    @Autowired
    Demo demo;
    
    public void call(Object obj) {
        demo.insertDb(obj);
    }
}

2,一句话说明实现原理

通过注解标记类中的方法,在Spring框架启动时如果发现注入的SpringBean中有该注解,就通过Spring AOP 使用 JDK 动态代理(代理接口时,推荐这种,效率更高)或者 CGLIB(代理class时) 为目标对象创建代理对象,在该对象中方法被调用时实际被调用的是代理对象中对应的方法,而这个代理方法中增加了我们的增强的逻辑,这样通过注解实现方法增强的功能就实现了。

3.错误配置、无效用法及原因说明

3.1 配置有误导致未生效

checkList:
1,是否遗漏了@Aspect@Component两个注解,或者配置的扫描路径未包含
2,@Pointcu定义切面的参数 AOP-execution 表达式是否正确
3,@Around@Before@After的参数 pointcut expression(一般就是简单的函数名加括号)是否正确如
4,果项目中用了以XML配置的SpringMVC就需要在 SpringMVC 的配置文件中开启代理模式:<aop:aspectj-autoproxy expose-proxy="true"></aop:aspectj-autoproxy>

3.2 使用方式错误导致没有调用代理对象的方法

根据2小节原理说明可知,要注解生效关键在于要要调用代理对象的方法,以下情况不能调用到代理对象的方法,所以注解无效
checkList:
1 ,注解在非SpringBean对象方法上时无效(类没有加@Service@Component等注解也没有在XML中配置,使用时不是通过@Autowired@Resource声明而是通过new方法生成的对象)
2,注解在 final 修饰的方法上时无效(CGLIB通过继承实现代理,方法不能被覆写就不能被代理)
2,注解方法在类内部被调用时无效


本文主要参考
https://www.jianshu.com/p/e130b5b73c1b by 泡芙掠夺者
https://bbs.csdn.net/topics/391049202?page=1 
Spring MVC中AOP无效、不起作用,解决方案之一_spring mvc 代理失效-CSDN博客  (SpringMVC项目配置)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值