zoukankan      html  css  js  c++  java
  • Spring Aop表达式以及EL表达式处理

       在Spring AOP 中,通常需要借助AspectJ 的切点表达式语言来定义切点。重要的是Spring 中仅支持AspectJ切点指示器的一个子集。

    Spring 支持的AspectJ的切点指示器
    AspectJ 指示器 描述
    args() 限制连接点匹配参数为执行类型的执行方法
    @args() 限制连接点匹配参数由执行注解标注的执行方法
    execution() 匹配连接点的执行方法
    this() 限制连接点匹配AOP代理的Bean引用类型为指定类型的Bean
    target() 限制连接点匹配目标对象为指定类型的类
    @target() 限制连接点匹配目标对象被指定的注解标注的类
    within() 限制连接点匹配匹配指定的类型
    @within() 限制连接点匹配指定注解标注的类型
    @annotation 限制匹配带有指定注解的连接点

    Spring AOP 中常用的是:

    execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
              throws-pattern?)
    

      

     匹配所有

           execution("* *.*(..)")

    匹配所有以set开头的方法

            execution("* *.set*(..))

    匹配指定包下所有的方法

            execution("* com.david.biz.service.impl.*(..))

    匹配指定包以及其子包下的所有方法

            execution("* com.david..*(..)")

    匹配指定包以及其子包下 参数类型为String 的方法

            execution("* com.david..*(java.lang.String))

      

    @Service("bookService")
    public class BookServiceImpl implements BookService {
    
        private static final Logger logger      = LogManager.getLogger(BookServiceImpl.class);
        public static final String  ADD_BOOK    = "insert into t_book(id,name) values(1,'duck-j2ee')";
    
        public static final String  DELETE_BOOK = "delete from  t_book where id=1";
    
        private JdbcTemplate        jdbcTemplate;
        @Autowired
        private BookDao             bookDao;
    
        public void addBook() throws Exception {
            Book book = new Book();
            book.setName("ibatis");
            book.setPrice(11);
            bookDao.insert(book);
            throw new UnRollbackException("受检查异常,不会回滚");
        }
    
        public void deleteBook(int id) {
            try {
                bookDao.deleteById(id);
            } catch (SQLException e) {
                logger.error("", e);
            }
        }
    
        @LoggingRequired
        public void addNewBook(String name, int price) {
            try {
                Book book = new Book();
                book.setName(name);
                book.setPrice(price);
                bookDao.insert(book);
                List<Book> lists = bookDao.selectAll();
                System.out.println(lists);
            } catch (SQLException e) {
                logger.error("", e);
            }
        }
    
        public void addUserBook() {
            jdbcTemplate.execute("insert into t_book(id,name) values(3,'UserBook')");
        }
    
        /**
         * Setter method for property <tt>jdbcTemplate</tt>.
         *
         * @param jdbcTemplate value to be assigned to property jdbcTemplate
         */
        public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
            this.jdbcTemplate = jdbcTemplate;
        }
    
        /**
         * @see com.david.biz.service.BookService#queryAll()
         */
        public List<Book> queryAll() {
            try {
                return bookDao.selectAll();
            } catch (SQLException e) {
                logger.error("", e);
            }
            return null;
        }
    
    }
    

      

    /**
     * execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
              throws-pattern?)
     *arg()  限制连接点匹配参数为指定类型的执行方法
     *@args() 限制连接点匹配参数由执行注解标注的执行
     *execution() 用于匹配连接点的执行方法
     *this() 限制连接点匹配AOP代理的Bean引用为执行类型的类
     *target() 限制连接点匹配目标对象为指定类型的类
     *@target() 限制连接点匹配特定的执行对象,这些对象应具备指定的注解类型
     *@annotation()限制匹配带有指定注解的连接点
     *
     *
     *
     * @author zhangwei_david
     * @version $Id: LogAspect.java, v 0.1 2014年11月29日 下午1:10:13 zhangwei_david Exp $
     */
    @Component
    @Aspect
    public class LogAspect {
        private static final Logger logger = LogManager.getLogger(LogAspect.class);
    
        /**
         * 匹配参数是任何类型,任何数量 且在com,david.biz包或子包下的方法
         */
        @Pointcut("args(..)&&within(com.david.biz..*)")
        public void arg() {
    
        }
    
        @Pointcut("@args(com.david.aop.LoggingRequired)")
        public void annotationArgs() {
    
        }
    
        @Pointcut("@annotation(com.david.aop.LoggingRequired)")
        public void logRequiredPointcut() {
    
        }
    
        @Pointcut("args(java.lang.String,*)")
        public void argsWithString() {
    
        }
    
        @Pointcut("target(com.david.biz.service.impl.BookServiceImpl)")
        public void targetPointcut() {
    
        }
    
        @Pointcut("@target(org.springframework.stereotype.Service)")
        public void targetAnnotation() {
    
        }
    
        //    @Around("execution(* org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(..))")
        //    public Object aa(ProceedingJoinPoint pjp) throws Throwable {
        //        try {
        //            Object retVal = pjp.proceed();
        //            System.out.println(retVal);
        //            return retVal;
        //        } catch (Exception e) {
        //            System.out.println("异常");
        //            return null;
        //        }
        //    }
        @Before(value = "logRequiredPointcut()")
        public void before(JoinPoint joinPoint) {
            LogUtils.info(logger,
                " 连接点表达式@annotation(com.david.aop.LoggingRequired) - method={0} has been visited",
                joinPoint.getSignature().getName());
        }
    
        @Before(value = "arg()")
        public void beforeArg(JoinPoint joinPoint) {
            LogUtils.info(logger,
                "连接点表达式:args(..)&&within(com.david.biz..*)  method ={0}, args ={1},target={2}",
                joinPoint.getSignature().getName(), ToStringBuilder.reflectionToString(
                    joinPoint.getArgs(), ToStringStyle.SHORT_PREFIX_STYLE), joinPoint.getTarget()
                    .getClass().getName());
        }
    
        @Before(value = "argsWithString()")
        public void beforeArgWithString(JoinPoint joinPoint) {
            LogUtils.info(logger, "连接点表达式:args(java.lang.String,*)  method={0} ,args ={1},target={2}",
                joinPoint.getSignature().getName(), ToStringBuilder.reflectionToString(
                    joinPoint.getArgs(), ToStringStyle.SHORT_PREFIX_STYLE), joinPoint.getTarget()
                    .getClass().getName());
        }
    
        @Before(value = "annotationArgs()")
        public void beforeAnnotationArgs(JoinPoint joinPoint) {
            LogUtils
                .info(
                    logger,
                    "连接点表达式:@args(com.david.annotation.validate.Length,*)  method={0} ,args ={1},target={2}",
                    joinPoint.getSignature().getName(), ToStringBuilder.reflectionToString(
                        joinPoint.getArgs(), ToStringStyle.SHORT_PREFIX_STYLE), joinPoint.getTarget()
                        .getClass().getName());
        }
    
        @Before(value = "targetPointcut()")
        public void beforeTarget(JoinPoint joinPoint) {
            LogUtils
            .info(
                logger,
                "连接点表达式:target(com.david.biz.service.impl.BookServiceImpl)  method={0} ,args ={1},target={2}",
                joinPoint.getSignature().getName(), ToStringBuilder.reflectionToString(
                    joinPoint.getArgs(), ToStringStyle.SHORT_PREFIX_STYLE), joinPoint.getTarget()
                    .getClass().getName());
        }
    
        @Before(value = " targetAnnotation()")
        public void beforeTargetAnnotation(JoinPoint joinPoint) {
            LogUtils
                .info(
                    logger,
                    "连接点表达式:@target(org.springframework.stereotype.Service)  method={0} ,args ={1},target={2}",
                    joinPoint.getSignature().getName(), ToStringBuilder.reflectionToString(
                        joinPoint.getArgs(), ToStringStyle.SHORT_PREFIX_STYLE), joinPoint.getTarget()
                        .getClass().getName());
        }
    }
    

      

    2014-12-01 11:14:39  [ main:1577 ] - [ INFO ]   连接点表达式@annotation(com.david.aop.LoggingRequired) - method=addNewBook has been visited
    2014-12-01 11:14:39  [ main:1587 ] - [ INFO ]  连接点表达式:args(..)&&within(com.david.biz..*)  method =addNewBook, args =Object[][{Junit  Test,1000}],target=com.david.biz.service.impl.BookServiceImpl
    2014-12-01 11:14:39  [ main:1588 ] - [ INFO ]  连接点表达式:args(java.lang.String,*)  method=addNewBook ,args =Object[][{Junit  Test,1000}],target=com.david.biz.service.impl.BookServiceImpl
    2014-12-01 11:14:39  [ main:1588 ] - [ INFO ]  连接点表达式:target(com.david.biz.service.impl.BookServiceImpl)  method=addNewBook ,args =Object[][{Junit  Test,1000}],target=com.david.biz.service.impl.BookServiceImpl
    2014-12-01 11:14:39  [ main:1589 ] - [ INFO ]  连接点表达式:@target(org.springframework.stereotype.Service)  method=addNewBook ,args =Object[][{Junit  Test,1000}],target=com.david.biz.service.impl.BookServiceImpl
    2014-12-01 11:14:39  [ main:1589 ] - [ INFO ]  连接点表达式:args(..)&&within(com.david.biz..*)  method =insert, args =Object[][{Book[id=0,name=Junit  Test,price=1000]}],target=com.david.biz.dao.impl.BookDaoImpl
    2014-12-01 11:14:39  [ main:1590 ] - [ INFO ]  连接点表达式:@args(com.david.annotation.validate.Length,*)  method=insert ,args =Object[][{Book[id=0,name=Junit  Test,price=1000]}],target=com.david.biz.dao.impl.BookDaoImpl
    2014-12-01 11:14:39  [ main:1591 ] - [ INFO ]  连接点表达式:args(java.lang.String,*)  method=insert ,args =Object[][{demo.insert,Book[id=0,name=Junit  Test,price=1000]}],target=com.ibatis.sqlmap.engine.impl.SqlMapClientImpl
     
    

      

      在AOP中如果还需要获取方法的参数值应该怎么处理呢?

        /**
         * 获取被拦截方法对象
         * <p/>
         * MethodSignature.getMethod() 获取的是顶层接口或者父类的方法对象
         * 而缓存的注解在实现类的方法上
         * 所以应该使用反射获取当前对象的方法对象
         */
        public Method getMethod(ProceedingJoinPoint pjp) {
            //获取参数的类型
            Class[] argTypes = ((MethodSignature) pjp.getSignature()).getMethod().getParameterTypes();
    
            Method method = null;
            try {
                method = pjp.getTarget().getClass().getMethod(pjp.getSignature().getName(), argTypes);
            } catch (NoSuchMethodException | SecurityException e) {
                logger.error("操作日志记录异常 :", e);
            }
            return method;
    
        }
    

      

    private PromotionOpLog initPromotionOpLog(OpLogAnnotation opLogAnnotation, Method method, Object[] args) {
            PromotionOpLog opLog = new PromotionOpLog();
    
            opLog.setOpModule(opLogAnnotation.opModule());
            opLog.setOpAction(opLogAnnotation.opAction());
    
            try {
                //获取被拦截方法参数名列表(使用Spring支持类库)
                LocalVariableTableParameterNameDiscoverer u =
                        new LocalVariableTableParameterNameDiscoverer();
                String[] paraNameArr = u.getParameterNames(method);
    
                //SPEL上下文
                StandardEvaluationContext context = new StandardEvaluationContext();            //把方法参数放入SPEL上下文中
                for (int i = 0; i < paraNameArr.length; i++) {
                    context.setVariable(paraNameArr[i], args[i]);
                }
    
                //使用SPEL进行key的解析
                if (StringUtils.isNotBlank(opLogAnnotation.opPkId())) {
                    opLog.setOpPkId(parser.parseExpression(opLogAnnotation.opPkId()).getValue(context, String.class));
                }
    
                if (StringUtils.isNotBlank(opLogAnnotation.creator())) {
                    opLog.setCreator(parser.parseExpression(opLogAnnotation.creator()).getValue(context, String.class));
                }
    
                Map<String, Object> opInfo = Maps.newHashMap();
                StringBuffer path = new StringBuffer();
                path.append(method.getDeclaringClass().getName()).append(".").append(method.getName());
                opInfo.put("path", path);
                for (int i = 0; i < paraNameArr.length; i++) {
                    if (i < args.length) {
                        if (args[i] instanceof Serializable) {
                            opInfo.put(paraNameArr[i], args[i]);
                        } else {
                            String parameterValue = null == args[i] ? "" : args[i].toString();
                            opInfo.put(paraNameArr[i], parameterValue);
                        }
                    } else {
                        opInfo.put(paraNameArr[i], "");
                    }
                }
                opLog.setOpInfo(FastJsonUtil.toJSONString(opInfo));
                opLog.setCreateTime(new Timestamp(new Date().getTime()) );
            } catch (Exception e) {
                logger.info("操作日志记录-解析参数异常", e);
            }
            return opLog;
        }
    

      使用示例:

    @OpLogAnnotation(opPkId = "#schemeVO.schemeId", opModule = OpLogConstant.OP_MODULE_ACTIVITY, opAction =
        OpLogConstant.OP_ACTION_UPDATE, creator = "#schemeVO.creator")
        public BaseResult<Long> saveAndPublishAndPauseScheme(ActivitySchemeVO schemeVO) 
    

      这样就可以通过AOP方式记录日志了

  • 相关阅读:
    net.sf.fmj.media.cdp.civil.CaptureDevicePlugger addCaptureDevices解决方法
    SVN快速入门教程
    Struts 2详细工作流程
    未能加载.NET基类问题
    图片上传的例子
    一个.NET发邮件的简单例子
    一种巧妙的删除程序自己的方法
    oracle的问题
    javascript 中对Trim()的实现
    SQL Server 不存在或访问被拒绝的问题
  • 原文地址:https://www.cnblogs.com/wei-zw/p/8797814.html
Copyright © 2011-2022 走看看