• AOP切面详解


    一、spring-aop.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:task="http://www.springframework.org/schema/task" xmlns:context="http://www.springframework.org/schema/context"
        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/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd   ">
        <!-- 启动@AspectJ支持 -->
        <aop:aspectj-autoproxy proxy-target-class="true"/>
        <context:component-scan base-package="hongmoshui.com.cnblogs.www.base.aop" />
    </beans>

    二、spring-mybatis.xml文件和spring-mvc.xml文件中,分别导入spring-aop.xml的配置

    spring-mybatis.xml【service和dao层的注解有效】:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 
       xmlns:context
    ="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"> <!--读取jdbc资源文件 --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <!-- 允许JVM参数覆盖 --> <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /> <!-- 忽略没有找到的资源文件 --> <property name="ignoreResourceNotFound" value="true" /> <!-- 配置资源文件 --> <property name="locations"> <list> <value>classpath:properties/jdbc.properties</value> </list> </property> </bean> <!-- 配置数据源 --> <bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close"> <!-- 数据库驱动 --> <property name="driverClass" value="${master.jdbc.driver}" /> <!-- 相应驱动的jdbcUrl --> <property name="jdbcUrl" value="${master.jdbc.url}" /> <!-- 数据库的用户名 --> <property name="username" value="${master.jdbc.username}" /> <!-- 数据库的密码 --> <property name="password" value="${master.jdbc.password}" /> <!-- 检查数据库连接池中空闲连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0 --> <property name="idleConnectionTestPeriod" value="60" /> <!-- 连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0 --> <property name="idleMaxAge" value="30" /> <!-- 每个分区最大的连接数 --> <!-- 判断依据:请求并发数 --> <property name="maxConnectionsPerPartition" value="100" /> <!-- 每个分区最小的连接数 --> <property name="minConnectionsPerPartition" value="5" /> </bean> <!-- 扫描包 --> <context:component-scan base-package="hongmoshui.com.cnblogs.www.*.service.impl,hongmoshui.com.cnblogs.www.*.dao.impl" /> <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 自动扫描mapping.xml文件 --> <property name="mapperLocations" value="classpath:mappers*/*Mapper.xml"></property> </bean> <!-- DAO接口所在包名,Spring会自动查找其下的类 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="hongmoshui.com.cnblogs.www.base.dao.impl,hongmoshui.com.cnblogs.www.work.dao" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> </bean> <!-- 定义事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 导入aop配置 --> <import resource="classpath*:/spring/spring-aop.xml" /> </beans>

    spring-mvc.xml【controller层的注解有效】:

    <?xml version="1.0" encoding="UTF-8"?>  
    <beans xmlns="http://www.springframework.org/schema/beans"  
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"  
        xmlns:context="http://www.springframework.org/schema/context"  
        xmlns:mvc="http://www.springframework.org/schema/mvc" 
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans    
                            http://www.springframework.org/schema/beans/spring-beans-3.1.xsd    
                            http://www.springframework.org/schema/context    
                            http://www.springframework.org/schema/context/spring-context-3.1.xsd    
                            http://www.springframework.org/schema/mvc    
                            http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd 
                            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd   ">  
        
        <!-- 配置注解驱动 -->
        <mvc:annotation-driven/>
        
        <!-- 扫描controller包 -->
        <context:component-scan base-package="hongmoshui.com.cnblogs.www.*.controller"/>
        
        <!-- 配置视图解析器 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <property name="suffix" value=".jsp"/>
        </bean>
        <!-- 对静态资源文件的访问 ,不支持访问WEB-INF目录 --> 
        <!-- <mvc:default-servlet-handler/> -->
        <!-- 对静态资源文件的访问 ,可以访问任何目录,包括访问WEB-INF目录 --> 
        <mvc:resources mapping="/resources/**" location="/resources/" />
        <!-- 导入aop配置 -->
        <import resource="classpath*:/spring/spring-aop.xml" />
    </beans>  

     三、自定义注解类【连接点】

    package hongmoshui.com.cnblogs.www.work.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface Log
    {
        /**
         * 方法名
         * @author 洪墨水
         */
        public String name() default "";
    
        /**
         * 描述
         * @author 洪墨水
         */
        public String description() default "no description";
    }

    参数定义:

    @Target 注解

    功能:指明了修饰的这个注解的使用范围,即被描述的注解可以用在哪里。

    ElementType的取值包含以下几种: 

    • TYPE:类,接口或者枚举

    • FIELD:域,包含枚举常量

    • METHOD:方法

    • PARAMETER:参数

    • CONSTRUCTOR:构造方法

    • LOCAL_VARIABLE:局部变量

    • ANNOTATION_TYPE:注解类型

    • PACKAGE:包

    @Retention 注解

    功能:指明修饰的注解的生存周期,即会保留到哪个阶段。

    RetentionPolicy的取值包含以下三种:

    • SOURCE:源码级别保留,编译后即丢弃。

    • CLASS:编译级别保留,编译后的class文件中存在,在jvm运行时丢弃,这是默认值。

    • RUNTIME: 运行级别保留,编译后的class文件中存在,在jvm运行时保留,可以被反射调用。

    @Documented 注解

    功能:指明修饰的注解,可以被例如javadoc此类的工具文档化,只负责标记,没有成员取值。

    @Inherited注解

    功能:允许子类继承父类中的注解。

    四、自定义切面类

    package hongmoshui.com.cnblogs.www.base.aop;
    
    import java.io.IOException;
    import java.lang.reflect.Method;
    import java.util.Calendar;
    
    import org.apache.log4j.Logger;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    import com.alibaba.fastjson.JSON;
    
    import hongmoshui.com.cnblogs.www.base.utils.TimeUtil;
    import hongmoshui.com.cnblogs.www.work.annotation.Log;
    
    /**
     * 日志注解的切面类
     * @author 洪墨水
     */
    @Aspect
    @Component
    public class LogAspect
    {
        /**
         * 日志记录log
         */
        public transient Logger log = Logger.getLogger(getClass());
    
        @Around(value = "@annotation(l)", argNames = "l")
        public Object aroundBase(ProceedingJoinPoint point, Log l)
        {
            RecordMessage recordMessage = new RecordMessage();
            Long startTime = System.currentTimeMillis();
            Object object = null;
    
            try
            {
                /* 记录下当前时间 作为请求起始时间 */
                recordMessage.setRequestTime(TimeUtil.getLongDateString(Calendar.getInstance().getTime()));
    
                /* 获取请求的信息 */
                getRequestParams(point, recordMessage);
    
                /* 执行请求的方法 */
                object = point.proceed();
    
                /* 记录下当前时间 作为响应时间 */
                recordMessage.setResponseTime(TimeUtil.getLongDateString(Calendar.getInstance().getTime()));
    
                /* 记录响应参数 */
                recordMessage.setResponseParames(object == null ? "" : JSON.toJSONString(object));
            }
            catch (Throwable e)
            {
                log.warn("proceed GW Interface throwable, ", e);
            }
            finally
            {
                Long endTime = System.currentTimeMillis();
                recordMessage.setCostTime(endTime - startTime);
                /* 记录接口日志 */
                log.info(recordMessage.toString());
            }
            return object;
        }
    
        /**
         * 从切点中解析出该切点对应的方法
         * @param point point
         * @throws ClassNotFoundException
         * @throws IOException
         * @author 洪墨水
         */
        private void getRequestParams(ProceedingJoinPoint point, RecordMessage recordMessage) throws ClassNotFoundException, IOException
        {
            /* 类名 */
            String targetObject = point.getTarget().getClass().getName();
            /* 方法名 */
            String methodName = point.getSignature().getName();
    
            recordMessage.setTargetObject(targetObject);
            recordMessage.setMethod(methodName);
    
            Object[] args = point.getArgs();
    
            Class<?> targetClass = Class.forName(targetObject);
    
            Method[] methods = targetClass.getMethods();
    
            StringBuilder requestBuilder = new StringBuilder(0);
    
            /**
             * 遍历方法 获取能与方法名相同且请求参数个数也相同的方法
             */
            for (Method method : methods)
            {
                if (!method.getName().equals(methodName))
                {
                    continue;
                }
    
                Class<?>[] classes = method.getParameterTypes();
    
                if (classes.length != args.length)
                {
                    continue;
                }
    
                for (int index = 0; index < classes.length; index++)
                {
                    requestBuilder.append(args[index] == null ? "" : JSON.toJSONString(args[index]));
                }
    
                recordMessage.setRequestParames(requestBuilder.toString());
            }
    
            return;
        }
    
        @Pointcut(value = "execution(* hongmoshui.com.cnblogs.www.work.service.impl.*.*(..))")
        public void getValuePointCut()
        {
        }
    
        @After(value = "getValuePointCut()")
        public void after()
        {
            System.out.println("方法执行结束...");
        }
    
    }
    
    /**
     * 日志记录对象
     * @author 洪墨水
     */
    class RecordMessage
    {
        /**
         * 请求的方法
         */
        private String method;
    
        /**
         * 请求方法所在的对象
         */
        private String targetObject;
    
        /**
         * 请求参数
         */
        private String requestParames;
    
        /**
         * 请求时间
         */
        private String requestTime;
    
        /**
         * 响应时间
         */
        private String responseTime;
    
        /**
         * 响应参数
         */
        private String responseParames;
    
        /**
         * 请求的来源IP
         */
        private String requestIp;
    
        /**
         * 方法执行的耗时,毫秒
         */
        private long costTime;
    
        /**
         * 请求的方法
         */
        public String getMethod()
        {
            return method;
        }
    
        /**
         * 请求的方法
         */
        public void setMethod(String method)
        {
            this.method = method;
        }
    
        /**
         * 请求方法所在的对象
         */
        public String getTargetObject()
        {
            return targetObject;
        }
    
        /**
         * 请求方法所在的对象
         */
        public void setTargetObject(String targetObject)
        {
            this.targetObject = targetObject;
        }
    
        /**
         * 请求参数
         */
        public String getRequestParames()
        {
            return requestParames;
        }
    
        /**
         * 请求参数
         */
        public void setRequestParames(String requestParames)
        {
            this.requestParames = requestParames;
        }
    
        /**
         * 请求时间
         */
        public String getRequestTime()
        {
            return requestTime;
        }
    
        /**
         * 请求时间
         */
        public void setRequestTime(String requestTime)
        {
            this.requestTime = requestTime;
        }
    
        /**
         * 响应时间
         */
        public String getResponseTime()
        {
            return responseTime;
        }
    
        /**
         * 响应时间
         */
        public void setResponseTime(String responseTime)
        {
            this.responseTime = responseTime;
        }
    
        /**
         * 响应参数
         */
        public String getResponseParames()
        {
            return responseParames;
        }
    
        /**
         * 响应参数
         */
        public void setResponseParames(String responseParames)
        {
            this.responseParames = responseParames;
        }
    
        /**
         * 请求的来源IP
         */
        public String getRequestIp()
        {
            return requestIp;
        }
    
        /**
         * 请求的来源IP
         */
        public void setRequestIp(String requestIp)
        {
            this.requestIp = requestIp;
        }
    
        /**
         * 方法执行的耗时,毫秒
         */
        public long getCostTime()
        {
            return costTime;
        }
    
        /**
         * 方法执行的耗时,毫秒
         */
        public void setCostTime(long costTime)
        {
            this.costTime = costTime;
        }
    
        /**
         * toString
         * @return String String
         * @author 洪墨水
         */
        @Override
        public String toString()
        {
            StringBuilder sBuilder = new StringBuilder(0);
    
            sBuilder.append("method=").append(method);
            sBuilder.append(", targetObject=").append(targetObject);
            sBuilder.append(", requestParames=").append(requestParames);
            sBuilder.append(", requestTime=").append(requestTime);
            sBuilder.append(", responseTime=").append(responseTime);
            sBuilder.append(", responseParames=").append(responseParames);
            sBuilder.append(", requestIp=").append(requestIp);
            sBuilder.append(", costTime=").append(costTime);
    
            return sBuilder.toString();
        }
    
    }

    时间工具类:

    package hongmoshui.com.cnblogs.www.base.utils;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.TimeZone;
    
    import org.apache.commons.lang3.StringUtils;
    
    /**
     * 时间工具类
     * @author 洪墨水
     */
    public class TimeUtil
    {
        private static int i = 0;
    
        /**
         * 日期转换成 yyyy-MM-dd HH:mm:ss+时区形式 如:2019-04-24 19:18:03+0800
         * @param date 日期
         * @return 按格式返回日期
         * @author 洪墨水
         */
        public static String getDateString(Date date)
        {
            if (date == null)
            {
                return null;
            }
    
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ");
    
            return dateFormat.format(date);
        }
    
        /**
         * 日期转换成 yyyy-MM-dd HH:mm:ss 形式 如:2019-04-24 19:18:03
         * @param date 日期
         * @return 按格式返回日期
         * @author 洪墨水
         */
        public static String dateToString()
        {
            Calendar now = Calendar.getInstance();
            now.set(Calendar.SECOND, now.get(Calendar.SECOND) + i);
    
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            i++;
            if (i > 1)
            {
                i = 0;
            }
            return dateFormat.format(now.getTime());
        }
    
        /**
         * 日期转换成 yyyy-MM-dd HH:mm:ss+时区形式 如:2019-04-24 19:18:03+0800
         * @param date 日期
         * @return 按格式返回日期
         * @author 洪墨水
         */
        public static String getDateString(String date)
        {
            if (date == null)
            {
                return null;
            }
            return TimeUtil.getDateString(toDate(date, "yyyy-MM-dd HH:mm:ss"));
        }
    
        /**
         * 
         * String转 Date
         * @param date 日期
         * @param format 格式
         * @return 转换后日期
         * @author 洪墨水
         */
        public static Date toDate(String date, String format)
        {
            if (StringUtils.isEmpty(format))
            {
                format = "yyyy-MM-dd HH:mm:ss";
            }
            SimpleDateFormat df = new SimpleDateFormat(format);
            try
            {
                return df.parse(date);
            }
            catch (ParseException e)
            {
                return new Date();
            }
        }
    
        /**
         * 
         * String转 Date
         * @param date 日期
         * @param format 格式
         * @return 转换后日期
         * @author 洪墨水
         */
        public static Date toDate(String date)
        {
            return toDate(date, null);
        }
    
        /**
         * 将带时区的时间字符串转换成系统所在时区的时间 如:2019-04-24 19:18:03+0700 转换到东八区的时间为:2019-04-24
         * 20:18:03
         * @param dateformat 日期格式
         * @return 系统所在时区的时间
         * @throws ParseException [参数说明]
         * @author 洪墨水
         */
        public static Date convertToLocalDate(String dateformat) throws ParseException
        {
            SimpleDateFormat dFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ");
    
            Date date = dFormat.parse(dateformat);
    
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.setTimeZone(TimeZone.getDefault());
    
            return calendar.getTime();
        }
    
        /**
         * <获取当前时间N小时后的时间 >
         * @param n 小时
         * @return 日期
         * @author 洪墨水
         */
        public static Date getNextDate(int n)
        {
            Calendar now = Calendar.getInstance();
            now.set(Calendar.HOUR_OF_DAY, now.get(Calendar.HOUR_OF_DAY) + n);
            return now.getTime();
        }
    
        /**
         * <获取当前时间N天后的凌晨 >
         * @param n 天
         * @return 日期
         * @author 洪墨水
         */
        public static Date getMorningNextDate(int n)
        {
            Calendar now = Calendar.getInstance();
            now.set(Calendar.DATE, now.get(Calendar.DATE) + n);// 设置时间向前进n天
            now.set(Calendar.HOUR_OF_DAY, 0);
            now.set(Calendar.MINUTE, 0);
            now.set(Calendar.SECOND, 0);
            return now.getTime();
        }
    
        /**
         * <获取当前时间N小时后的整点时间 >
         * @param n 小时
         * @return 日期
         * @author 洪墨水
         */
        public static Date getNextHour(int n)
        {
            Calendar now = Calendar.getInstance();
            now.set(Calendar.DATE, now.get(Calendar.DATE));
            now.set(Calendar.HOUR_OF_DAY, now.get(Calendar.HOUR_OF_DAY) + n);// 设置时间向前进n小时
            return now.getTime();
        }
    
        /**
         * <获取当前时间N天后的凌晨【精确到毫秒】 >
         * @param n 前进天数
         * @return Date [日期]
         * @author 洪墨水
         */
        public static Date getMorningNextDateMillisecond(int n)
        {
            Calendar now = Calendar.getInstance();
            now.set(Calendar.DATE, now.get(Calendar.DATE) + n);// 设置时间向前进n天
            now.set(Calendar.HOUR_OF_DAY, 0);
            now.set(Calendar.MINUTE, 0);
            now.set(Calendar.SECOND, 0);
            now.set(Calendar.MILLISECOND, 0);
            return now.getTime();
        }
    
        /**
         * 比较
         * @param date 日期
         * @return 是否是今天
         * @author 洪墨水
         */
        public static boolean checkLastDate(Date date)
        {
            Date d = new Date();
            Calendar current = Calendar.getInstance();
            current.setTime(date);
            Calendar start = Calendar.getInstance();
            Calendar end = Calendar.getInstance();
            start.set(Calendar.YEAR, current.get(Calendar.YEAR));
            start.set(Calendar.MONTH, current.get(Calendar.MONTH));
            start.set(Calendar.DAY_OF_MONTH, current.get(Calendar.DAY_OF_MONTH));
            start.set(Calendar.HOUR_OF_DAY, 0);
            start.set(Calendar.MINUTE, 0);
            start.set(Calendar.SECOND, 0);
            end.set(Calendar.YEAR, current.get(Calendar.YEAR));
            end.set(Calendar.MONTH, current.get(Calendar.MONTH));
            end.set(Calendar.DAY_OF_MONTH, current.get(Calendar.DAY_OF_MONTH));
            end.set(Calendar.HOUR_OF_DAY, 23);
            end.set(Calendar.MINUTE, 59);
            end.set(Calendar.SECOND, 59);
            if (d.after(start.getTime()) && d.before(end.getTime()))
            {
                return true;
            }
            return false;
        }
    
        /**
         * 获取日期;格式:yyyy-MM-dd
         * @param date 日期
         * @return String yyyy-MM-dd格式的日期字符串
         * @author 洪墨水
         */
        public static String getDate(Date date)
        {
            SimpleDateFormat dFormat = new SimpleDateFormat("yyyy-MM-dd");
            dFormat.setTimeZone(TimeZone.getDefault());
            return dFormat.format(date);
        }
    
        /**
         * <获取年月>
         * @param date 时间
         * @return String [获取年月]
         * @author 洪墨水
         */
        public static String getDateYearAndMonth(Date date)
        {
            SimpleDateFormat dFormat = new SimpleDateFormat("yyyy-MM");
            dFormat.setTimeZone(TimeZone.getDefault());
            return dFormat.format(date);
        }
    
        /**
         * 获取有效时间
         * @return 有效时间
         * @author 洪墨水
         */
        public static int getExpireTime()
        {
            Calendar cal = Calendar.getInstance();
            cal.set(Calendar.HOUR_OF_DAY, 23);
            cal.set(Calendar.MINUTE, 59);
            cal.set(Calendar.SECOND, 59);
            return (int) ((cal.getTime().getTime() - new Date().getTime()) / 1000);
        }
    
        /**
         * <时间增加>
         * @param p 时间日期
         * @param number 要增加数
         * @param filed 域
         * @return Date [增加后的时间]
         * @author 洪墨水
         */
        public static Date addDate(Date p, int number, int filed)
        {
            Calendar cal = Calendar.getInstance();
            cal.setTime(p);
            cal.add(filed, number);
            return cal.getTime();
        }
    
        /**
         * <时间戳转日期时间>
         * @param s 时间戳
         * @return String [日期时间]
         * @author 洪墨水
         */
        public static String stampToDate(String s, String format)
        {
            if (StringUtils.isEmpty(format))
            {
                format = "yyyy-MM-dd HH:mm:ss";
            }
            String res;
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
            long lt = new Long(s);
            Date date = new Date(lt);
            res = simpleDateFormat.format(date);
            return res;
        }
        
        /**
         * 日期转换成 yyyy-MM-dd HH:mm:ss zzz+时区形式 如:2019-04-24 19:18:03 132+0800
         * @param date 日期
         * @return LongDate
         * @author 洪墨水
         */
        public static String getLongDateString(Date date)
        {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SZ");
    
            return dateFormat.format(date);
        }
    }

    aop切面类中的@Pointcut的用法:

    格式:

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

    括号中各个pattern分别表示:

    • 修饰符匹配(modifier-pattern?)
    • 返回值匹配(ret-type-pattern)可以为*表示任何返回值,全路径的类名等
    • 类路径匹配(declaring-type-pattern?)
    • 方法名匹配(name-pattern)可以指定方法名 或者 *代表所有, set* 代表以set开头的所有方法
    • 参数匹配((param-pattern))可以指定具体的参数类型,多个参数间用“,”隔开,各个参数也可以用“*”来表示匹配任意类型的参数,如(String)表示匹配一个String参数的方法;(*,String) 表示匹配有两个参数的方法,第一个参数可以是任意类型,而第二个参数是String类型;可以用(..)表示零个或多个任意参数
    • 异常类型匹配(throws-pattern?)
    • 其中后面跟着“?”的是可选项

    注:详细信息请看----切面AOP的切点@Pointcut用法

     四、测试类

    package hongmoshui.com.cnblogs.www.work.service.impl;
    
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.log4j.Logger;
    import org.apache.poi.hssf.usermodel.HSSFCell;
    import org.apache.poi.hssf.usermodel.HSSFCellStyle;
    import org.apache.poi.hssf.usermodel.HSSFFont;
    import org.apache.poi.hssf.usermodel.HSSFRow;
    import org.apache.poi.hssf.usermodel.HSSFSheet;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    import org.apache.poi.ss.util.CellRangeAddress;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import hongmoshui.com.cnblogs.www.base.dao.RedisClientDao;
    import hongmoshui.com.cnblogs.www.base.model.Result;
    import hongmoshui.com.cnblogs.www.work.annotation.Log;
    import hongmoshui.com.cnblogs.www.work.dao.TestDao;
    import hongmoshui.com.cnblogs.www.work.dao.TestQueryDao;
    import hongmoshui.com.cnblogs.www.work.model.UserInfo;
    import hongmoshui.com.cnblogs.www.work.service.TestService;
    
    @Service("testService")
    public class TestServiceImpl implements TestService
    {
        @Autowired
        private transient RedisClientDao redisClientDao;/**
         * 日志记录log
         */
        public transient Logger log = Logger.getLogger(getClass());
    
        @Log(name = "getValue")
        @Override
        public Result getValue(String key)
        {
            Result result = new Result();
            Object obj = redisClientDao.get(key);
            if (obj != null)
            {
                result.setSuccess(true);
                result.setMessage("取出成功!");
                result.put("value", obj);
                log.info("call redis get success! redis key:" + key + ",value:" + obj);
            }
            else
            {
                result.setSuccess(false);
                result.setMessage("取出失败!");
                log.error("call redis get failed! redis key:" + key + ",value:" + obj);
            }
            return result;
        }
    }

    测试结果:

    2019-04-22 15:36:51 [hongmoshui.com.cnblogs.www.base.aop.LogAspect]-[INFO] method=getValue, targetObject=hongmoshui.com.cnblogs.www.work.service.impl.TestServiceImpl, requestParames="hongmoshui_01", requestTime=2019-04-22 15:36:51 134+0800, responseTime=2019-04-22 15:36:51 250+0800, responseParames={"message":"取出成功!","value":"我是01","success":true}, requestIp=null, costTime=119
    方法执行结束...

  • 相关阅读:
    (笔记)Linux内核学习(二)之进程
    (笔记)Linux内核学习(一)之内核介绍
    状态机思路在程序设计中的应用
    内存操作函数memmove,memcpy,memset
    linux下常用的几个时间函数:time,gettimeofday,clock_gettime,_ftime
    Camera ISO、快门、光圈、曝光这几个概念
    C语言中的指针和内存泄漏几种情况
    音视频文件码率与大小计算
    CC++中 fopen中文件打开方式的区别:
    常用DOS命令
  • 原文地址:https://www.cnblogs.com/hongmoshui/p/10694535.html
Copyright © 2020-2023  润新知