java - 为什么当前配置下,定义在service层的aop不生效?
天蓬老师
天蓬老师 2017-04-18 10:25:42
[Java讨论组]

我定义了controller层的aop,以及service等的aop,但是service层的不生效?我用Test类直接getBean,调用userService.xx(),service层aop生效,但是在web项目中就是不生效。我初步猜测是配置或者说加载顺序问题?

新的补充:

反复测试发现,当quartz与shiro同时使用时,service层的aop就会失效。目前不是太过确定原因,但是一种猜测是shiro自带的quartz与quartz.jar冲突导致的。但是问题来了,为什么他们冲突导致service层的aop失效呢?而controller层不失效?

spring-web.xml




    
    
    
    
    
    
    

    
    

    
    
    

    
    

    
    
        
        
        
    

    
    

    



spring-service.xml




    
    

    
    
        
    

    
    



BindingResultAop.java

package com.yingjun.ssm.aop;

import com.yingjun.ssm.dto.BaseResult;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;

/**
 *
 * 采用AOP的方式处理@Valid 参数验证。
 */
@Component
@Aspect
public class BindingResultAop {
    private static final Logger LOG = LoggerFactory.getLogger(BindingResultAop.class);

    @Pointcut("execution(* com.yingjun.ssm.web.*.*(..))")
    public void bindingResultPointcut(){
        //该方法的内容不重要,该方法的本身只是个标识,供@Pointcut注解依附
    }

    /**
     * Aspect = Advice + Pointcut
     * Advice: @Around
     * Pointcut: execution(* com.yingjun.ssm.web.*.*(..))
     */
    @Around("bindingResultPointcut()")
    public Object aroundAdvice(ProceedingJoinPoint jp) throws Throwable{
        System.out.println("--->BindingResultAop start...");
        String className = jp.getTarget().getClass().getName();
        String methodName = jp.getSignature().getName();
        LOG.info("before " + className + "." + methodName + "() invoking!");

        // 遍历参数,找到BindingResult,判断是否hasError
        BindingResult bindingResult = null;
        for(Object arg: jp.getArgs()){
            if(arg instanceof BindingResult){
                bindingResult = (BindingResult) arg;
            }
        }
        if(bindingResult != null){
            if(bindingResult.hasErrors()){
                LOG.info("--->bindingResult hasError!");
                String errorInfo="["+bindingResult.getFieldError().getField()+"]"+bindingResult.getFieldError().getDefaultMessage();
                return new BaseResult(false, errorInfo);
            }
        }

        // 执行目标方法
        return jp.proceed();
    }
}

ClearCacheAop.java

package com.yingjun.ssm.aop;

import com.yingjun.ssm.cache.RedisCache;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.asm.AnnotationVisitor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 *
 * 采用AOP的方式处理: XXService关于数据更新(增删改)时,缓存的清理。
 */
@Component
@Aspect
public class ClearCacheAop {
    private static final Logger LOG = LoggerFactory.getLogger(ClearCacheAop.class);
    private static final String[] UPDATE_USER_MOTHOD = new String[]{"createUser", "updateUser", "deleteUser", "changePassword"};
    private static final String[] UPDATE_ROLE_MOTHOD = new String[]{"createRole", "updateRole", "deleteRole"};
    private static final String[] UPDATE_RESOURCE_MOTHOD = new String[]{"createResource", "updateResource", "deleteResource"};

    @Autowired
    private RedisCache cache;

    // 声明切入点
    @Pointcut("execution(* com.yingjun.ssm.service..*.*(..))")
    public void clearCachePointcut(){}

    @Before("clearCachePointcut()")
    public void beforeAdvice(JoinPoint jp) {
        System.out.println("--->clearCachePointcut start...");
        String className = jp.getTarget().getClass().getName();
        String methodName = jp.getSignature().getName();
        LOG.info("before " + className + "." + methodName + "() invoking!");

        if(StringUtils.contains(className, "UserService") && ArrayUtils.contains(UPDATE_USER_MOTHOD, methodName)){
            // 此时缓存中的数据不是最新的,需要对缓存进行清理(具体的缓存策略还是要根据具体需求制定)
            String cache_key = RedisCache.CAHCENAME + "|UserService|*";
            cache.deleteCacheWithPattern(cache_key);
            LOG.info("aop: delete cache with key: " + cache_key);
        } else if(StringUtils.contains(className, "RoleService") && ArrayUtils.contains(UPDATE_ROLE_MOTHOD, methodName)){
            String cache_key = RedisCache.CAHCENAME + "|RoleService|*";
            cache.deleteCacheWithPattern(cache_key);
            LOG.info("aop: delete cache with key: " + cache_key);
        } else if(StringUtils.contains(className, "ResourceService") && ArrayUtils.contains(UPDATE_RESOURCE_MOTHOD, methodName)){
            String cache_key = RedisCache.CAHCENAME + "|ResourceService|*";
            cache.deleteCacheWithPattern(cache_key);
            LOG.info("aop: delete cache with key: " + cache_key);
        }
    }
}

spring-shiro.xml




    
    
        
    

    
    
        
        
        
        
    

    
    
        
        
        
        
        
        
    

    
    

    
    
        
        
        
    

    
        
        
        
    

    
    
        
        
        
    

    
    
        
        
    

    
    
        
        
    

    
    
        
        
        
        
        
        
        
    

    
    
    
        
        
        
    

    
    
        
        
    

    
    
    
    
        
        
        
        
    

    
    
        
        
        
            
                
            
        
        
            
                /static/** = anon 
                /welcome = anon  
                /login = authc   
                /register = anon
                /logout = logout 
                /authenticated = authc
                /** = user       
            
        
    

    
    
    

    
    
        
    



spring-quartz.xml




    
    
    
    
     
     

天蓬老师
天蓬老师

欢迎选择我的课程,让我们一起见证您的进步~~

全部回复(2)
巴扎黑

应该是spring容器扫描范围的问题
<!-- 激活组件扫描功能,扫描aop的相关组件组件 -->

<context:component-scan base-package="com.yingjun.ssm.aop"/>

你在service.xml 里面加这句话试试
补充内容:另外一个配置文件去掉对应的内容

PHP中文网

反复测试发现,当quartz与shiro同时使用时,service层的aop就会失效。目前不是太过确定原因,但是一种猜测是shiro自带的quartz与quartz.jar冲突导致的。但是问题来了,为什么他们冲突导致service层的aop失效呢?而controller层不失效?

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号