一、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
方法執行結束...
