spring之AOP切面不生效!!!!!原因在这

Spring AOP切面日志记录与配置详解

首先配置好切面代码 打印日志

package com.rfca.aop;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Component
@Aspect
@Lazy(false)
public class Logaop {
    private Logger logger = LoggerFactory.getLogger(Logaop.class);
   // private final static String intfName = "Activity/starFireOrderDetailSyn";
    /**
     * 定义切入点:对要拦截的方法进行定义与限制,如包、类
     *
     * 1、execution(public * *(..)) 任意的公共方法
     * 2、execution(* set*(..)) 以set开头的所有的方法
     * 3、execution(* com.lingyejun.annotation.LoggerApply.*(..))com.lingyejun.annotation.LoggerApply这个类里的所有的方法
     * 4、execution(* com.lingyejun.annotation.*.*(..))com.lingyejun.annotation包下的所有的类的所有的方法
     * 5、execution(* com.lingyejun.annotation..*.*(..))com.lingyejun.annotation包及子包下所有的类的所有的方法
     * 6、execution(* com.lingyejun.annotation..*.*(String,?,Long)) com.lingyejun.annotation包及子包下所有的类的有三个参数,第一个参数为String类型,第二个参数为任意类型,第三个参数为Long类型的方法
     * 7、execution(@annotation(com.lingyejun.annotation.Lingyejun))
     */
    @Pointcut("execution(* com.rfca.newcontroller..*.*(..))")
    private void cutMethod() {

    }
    /**
     * 后置通知:在目标方法执行后调用,若目标方法出现异常,则不执行  后置通知完成计件
     */
    @Around("cutMethod()")
    public Object myLogger(ProceedingJoinPoint pjp) throws Throwable {
        long l = System.currentTimeMillis();
        //使用ServletRequestAttributes请求上下文获取方法更多
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String className = pjp.getSignature().getDeclaringTypeName();
        String methodName = pjp.getSignature().getName();
        //使用数组来获取参数
        Object[] array = pjp.getArgs();
        ObjectMapper mapper = new ObjectMapper();
        //执行函数前打印日志
        logger.info("调用前:{}:{},传递的参数为:{}", className, methodName, mapper.writeValueAsString(array));
        logger.info("URL:{}", request.getRequestURL().toString());
        logger.info("IP地址:{}", request.getRemoteAddr());
        //调用整个目标函数执行
        Object obj = pjp.proceed();
        //执行函数后打印日志
        logger.info("调用后:{}:{},返回值为:{}", className, methodName, mapper.writeValueAsString(obj));
        logger.info("耗时:{}ms", System.currentTimeMillis() - l);
        return obj;
    }

}

重点
需要在扫描controller的那个xml中配置 <aop:aspectj-autoproxy proxy-target-class=“true”/> 有时候配置到applicationContext.xml中是不生效的,
因为 切面类和 被代理的类都要由spring 或者springMVC管理
只有 Spring 生成的对象才有 AOP 功能,因为 Spring 生成的代理对象才有 AOP 功能。
切入的类和被切入的类必须是被spring管理的(springIOC),如果是自己new 出来的,切入无效。

而且所对应的切入方法不能是static 修饰的
可能是springmvc的bug吧。你把
aop:aspectj-autoproxy/
放到DispatcherServlet所对应的**-servlet.xml配置文件中,就可以了。

项目配置如下就可以生效了
在这里插入图片描述

结果

在这里插入图片描述

Spring AOP中,切面未生效是一个较为常见的问题,可能由多种原因导致。以下是一些常见原因及其对应的解决方案: ### 1. 切点表达式不正确 AOP切面是否能够生效,首先取决于切点表达式是否能够正确匹配到目标方法。如果`@Around`、`@Before`或`@After`等通知方法没有被触发,则很可能是由于切点表达式的配置有误。 **解决方案:** - 检查切点表达式是否正确匹配了目标方法,例如使用`execution(* com.example.service.*.*(..))`来匹配某个包下的所有方法。 - 可以通过打印日志或者调试的方式来验证切点是否被正确应用。 ### 2. 方法为静态方法 如果尝试拦截的方法是`static`修饰的,则AOP不会对其生效。这是因为Spring AOP默认使用JDK动态代理和CGLIB代理,而这两者都不支持对静态方法进行代理。 **解决方案:** - 避免对静态方法使用AOP切面,可以考虑将逻辑迁移到非静态方法中。 - 如果确实需要对静态方法进行增强,可以考虑使用AspectJ进行编译时织入[^3]。 ### 3. Spring配置问题 如果`<aop:aspectj-autoproxy/>`标签没有被正确配置,或者相关的AOP依赖没有被引入,也可能导致切面无法生效。 **解决方案:** - 确保在Spring配置文件中添加了`<aop:aspectj-autoproxy/>`标签,以启用自动代理功能。 - 检查项目的依赖管理,确保已经引入了必要的Spring AOP相关依赖,如`spring-aop`和`spring-aspects`[^4]。 ```xml <!-- 示例:Maven依赖配置 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>6.0.2</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>6.0.2</version> </dependency> ``` ### 4. 代理模式选择不当 Spring AOP默认情况下会根据目标类是否实现了接口来决定使用JDK动态代理还是CGLIB代理。如果没有正确设置`proxy-target-class`属性,可能会导致某些情况下的代理失败。 **解决方案:** - 在配置AOP时,可以通过设置`proxy-target-class="true"`来强制使用CGLIB代理,这样即使目标类没有实现接口也可以生成代理对象[^2]。 ```xml <aop:config proxy-target-class="true"> <!-- 其他配置 --> </aop:config> ``` ### 5. XML命名空间未正确声明 在使用基于XML的配置时,如果没有在`xsi:schemaLocation`中正确声明Spring AOP的命名空间,也会导致配置无效。 **解决方案:** - 确保在XML配置文件的根元素中包含了正确的命名空间声明,例如: ```xml <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 其他配置 --> </beans> ``` ### 6. 测试方法调用方式不正确 有时候,测试代码直接调用了目标方法,而不是通过Spring容器获取Bean后再调用,这会导致AOP切面不生效。 **解决方案:** - 确保测试代码是通过Spring容器获取Bean实例后调用目标方法,这样才能保证AOP代理机制正常工作。 ```java // 示例:通过Spring上下文获取Bean ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); MyService myService = (MyService) context.getBean("myService"); myService.doSomething(); // 此时doSomething()应该会被AOP拦截 ``` ### 7. 类或方法被final修饰 如果目标类或方法被声明为`final`,那么CGLIB代理将无法对其进行子类化,从而导致AOP不生效。 **解决方案:** - 尽量避免将需要被代理的类或方法标记为`final`。如果必须使用`final`,则需要寻找其他替代方案,比如重构代码结构。 ### 总结 以上列举了几种常见的Spring AOP切面不生效原因及相应的解决办法。实际开发过程中,建议开发者仔细检查配置文件、依赖关系以及切点表达式的准确性,并结合日志输出和调试工具来定位具体问题所在。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晴天M雨天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值