Java自定义AOP注解作用在类上不生效

问题描述

先上代码
aop自定义类

@Aspect
@Component
@Slf4j
public class LogAop {
    @Pointcut("@annotation(com.demo.aop.MyLog")
    public void MyLog() {
    }
	....
}

aop注解,作用在类、接口或枚举类上

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface MyLog{
    String value() default "";
}

这样设置,是不起作用的。因为@Pointcut里的参数值有问题。看下PointCut里的参数值各代表啥意思
execution:用于匹配方法执行的连接点
within:用于匹配指定类型内的方法执行
this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也* 类型匹配
target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配
args:用于匹配当前执行的方法传入的参数为指定类型的执行方法
@within:用于匹配所以持有指定注解类型内的类和方法
@target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解
@args:用于匹配当前执行的方法传入的参数持有指定注解的执行
@annotation:用于匹配当前执行方法持有指定注解的方法
bean:Spring AOP扩展的,AspectJ没有对于指示符,用于匹配特定名称的Bean对象的执行方法

问题原因

因为@annotation是匹配方法的,无法匹配类,所以应使用within

解决办法

@Aspect
@Component
@Slf4j
public class LogAop {
    @Pointcut("@within (com.demo.aop.MyLog")
    public void MyLog() {
    }
	....
}
<think>好的,我现在需要帮助用户解决如何通过自定义注解实现JavaAOP。首先,我得确认用户的需求。他们可能已经知道AOP的基本概念,但想通过自定义注解来更灵活地应用切面。接下来,我需要考虑实现步骤,可能需要提到Spring AOP或者AspectJ,因为这两个是常用的工具。 首先,我应该解释AOP的基本概念,比如切面、切点、通知等,确保用户理解这些基础。然后,重点放在如何创建自定义注解,并将其作为切点。可能需要分步骤讲解:定义注解、编写切面、配置AOP支持、使用注解等。 用户可能在使用Spring Boot,所以需要提到如何添加依赖,比如spring-boot-starter-aop。同时,要提醒他们启用AspectJ代理,通常使用@EnableAspectJAutoProxy注解。 在编写切面的时候,要详细说明如何用@Aspect标注,使用@Pointcut和@Around等通知型。特别是如何通过@annotation来指定自定义注解作为切点。这里需要确保语法正确,比如execution表达式和注解路径的写法。 还要考虑到异常处理,在环绕通知中如何处理ProceedingJoinPoint,调用proceed()方法,并捕获可能出现的异常。示例代码需要准确,避免拼写错误,比如注解的名称、包路径等。 另外,用户可能会遇到切面不生效的情况,需要给出常见的排查点,比如是否启用AOP注解是否正确应用、包扫描问题等。这部分可以帮助用户自行调试,提高解决问题的效率。 最后,总结步骤,强调自定义注解结合AOP的优势,比如解耦、代码简洁等。可能还需要比较Spring AOP和AspectJ的区别,让用户根据需求选择合适的方式。整个过程需要逻辑清晰,逐步引导用户完成实现,并确保示例代码的正确性和可复制性。</think>通过自定义注解实现Java AOP的步骤如下(以Spring Boot为例): $$ \text{实现流程} = \text{定义注解} \rightarrow \text{编写切面} \rightarrow \text{配置代理} \rightarrow \text{使用注解} $$ --- ### 一、添加依赖(Maven示例) ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> ``` --- ### 二、定义自定义注解 ```java @Target(ElementType.METHOD) // 标注在方法上 @Retention(RetentionPolicy.RUNTIME) // 运行时保留 public @interface CustomLog { String value() default ""; // 可定义注解参数 } ``` --- ### 三、编写切面(核心) ```java @Aspect @Component public class CustomLogAspect { // 定义切点:拦截所有带@CustomLog注解的方法 @Pointcut("@annotation(com.example.annotation.CustomLog)") public void logPointCut() {} // 环绕通知(最常用的通知型) @Around("logPointCut()") public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); // 获取注解信息 CustomLog annotation = method.getAnnotation(CustomLog.class); String logMessage = annotation.value(); try { // 前置处理 System.out.println("[AOP] 开始执行 " + method.getName() + " | 日志标记: " + logMessage); long start = System.currentTimeMillis(); Object result = joinPoint.proceed(); // 执行原方法 // 后置处理 long timeCost = System.currentTimeMillis() - start; System.out.println("[AOP] 方法执行完成 | 耗时: " + timeCost + "ms"); return result; } catch (Exception e) { // 异常处理 System.err.println("[AOP] 方法执行异常: " + e.getMessage()); throw e; } } } ``` --- ### 四、启用AOP支持 在配置添加注解: ```java @Configuration @EnableAspectJAutoProxy // 关键注解 public class AppConfig {} ``` --- ### 五、使用自定义注解 ```java @Service public class UserService { @CustomLog("用户创建日志") // 应用自定义注解 public void createUser(String username) { // 业务逻辑... } } ``` --- ### 六、常见问题排查 当切面不生效时,检查: 1. 是否添加了@EnableAspectJAutoProxy 2. 切面是否被Spring管理(@Component) 3. 注解的Retention是否是RUNTIME 4. 包扫描范围是否包含切面和被代理 --- ### 七、扩展建议 1. **通知型选择**: - `@Before`:方法执行前 - `@After`:方法执行后(无论是否异常) - `@AfterReturning`:方法正常返回后 - `@AfterThrowing`:方法抛出异常后 2. **性能优化**: $$ \text{优先使用} \ \texttt{@Around} \ \text{+} \ \texttt{joinPoint.proceed()} \ \text{组合} $$ 可以精确控制方法执行时机 3. **组合注解**: 可定义包含多个注解的元注解 ```java @CustomLog @Transactional @Target(ElementType.METHOD) public @interface SecureOperation {} ``` --- 通过这种方式,可以实现诸如日志记录、性能监控、权限校验等通用功能,且通过注解实现声明式编程,使核心业务代码保持简洁。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值