一、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
方法执行结束...

AOP切面详解的更多相关文章

  1. spring框架 AOP核心详解

    AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...

  2. Spring系列25:Spring AOP 切点详解

    本文内容 Spring 10种切点表达式详解 切点的组合使用 公共切点的定义 声明切点@Poincut @Poincut 的使用格式如下: @Poincut("PCD") // 切 ...

  3. Spring——面向切面编程(AOP)详解

    声明:本博客仅仅是一个初学者的学习记录.心得总结,其中肯定有许多错误,不具有参考价值,欢迎大佬指正,谢谢!想和我交流.一起学习.一起进步的朋友可以加我微信Liu__66666666 这是简单学习一遍之 ...

  4. Spring框架学习-Spring的AOP概念详解

    一.SpringAOP的概述. AOP(Aspect Oriented Programming),面向切面编程,通过预编译方式和运行期间动态代理实现程序的功能的统一维护的技术.AOP是OOP(面向对象 ...

  5. Spring AOP全面详解(超级详细)

    如果说 IOC 是 Spring 的核心,那么面向切面编程AOP就是 Spring 另外一个最为重要的核心@mikechen AOP的定义 AOP (Aspect Orient Programming ...

  6. SPRING AOC、AOP 概念详解

    AOC 依赖注入:就是通过容器来控制业务对象之间的依赖关系.也就是把需要的业务对象都放入容器中,需要注入时,通过反射技术来动态获取指定的对象,装配到当前使用对象.代替了原始的 new 来实现对象的实例 ...

  7. Spring框架学习05——AOP相关术语详解

    1.Spring AOP 的基本概述 AOP(Aspect Oriented Programing)面向切面编程,AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视.事务管理.安全检查 ...

  8. [转载] 多图详解Spring框架的设计理念与设计模式

    转载自http://developer.51cto.com/art/201006/205212_all.htm Spring作为现在最优秀的框架之一,已被广泛的使用,51CTO也曾经针对Spring框 ...

  9. Spring框架系列(9) - Spring AOP实现原理详解之AOP切面的实现

    前文,我们分析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的.本文主要介绍Spring AOP原理解析的切面实现过程(将切面类的所 ...

随机推荐

  1. iOS-Swizzle

    最后更新:2017-06-21 一.先说结论 void swizzleMethod(Class cls, SEL originalSelector, SEL swizzledSelector) { M ...

  2. [CSP-S模拟测试]:连连看(图论+容斥)

    题目传送门(内部题74) 输入格式 输入文件$link.in$ 第一行三个整数$n,m,k$,之间用空格隔开,$n,m$表示地图行数和列数,$k$表示每个方块周围相邻的位置(至多有$4$个,至少有$2 ...

  3. Java网络编程与NIO详解11:Tomcat中的Connector源码分析(NIO)

    本文转载 https://www.javadoop.com 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.c ...

  4. C++ Boost库的编译及使用

    https://www.jianshu.com/p/de1fda741beb https://www.cnblogs.com/weizhixiang/p/5804778.html Windows编译 ...

  5. Visual Studio使用技巧 +谷歌浏览器使用技巧总结

    一.总结下visual studio常用的使用技巧,有助于提高效率: 1.给代码行打标记:  ctrl + K :给行打标记:ctrl + K + N:切换标记,即使当前页关闭了,也可以适用此快捷键快 ...

  6. dropna()函数

    参数: axis:       default 0指行,1为列 how:       {‘any’, ‘all’}, default ‘any’指带缺失值的所有行;'all’指清除全是缺失值的 thr ...

  7. JSONPath解析json

    JSONPath - 用于JSON的XPath 用来解析多层嵌套的json数据;JsonPath 是一种信息抽取类库,是从JSON文档中抽取指定信息的工具. 考虑到接下来计划开发一个自动化测试平台,在 ...

  8. 您配置文件中的设置 (空密码的 root) 与 MySQL 默认管理员账户对应...的解决办法

    您配置文件中的设置 (空密码的 root) 与 MySQL 默认管理员账户对应.……解决办法很简单:1.修改root@localhost权限的密码. 打开wamp的phpmyadmin,进入它的管理界 ...

  9. centos7安装配置jdk、tomcat

    centos7安装jdk1.8 1.新建文件夹java,上传文件jdk-8u111-linux-x64.tar.gz到java文件夹 2.解压tar包: tar -zxvf jdk-8u111-lin ...

  10. 计算距离的SQL语句

    一,BEGINset @num=6378.138*2*ASIN(SQRT(POW(SIN((lat1*PI()/180-lat2*PI()/180)/2),2)+COS(lat1*PI()/180)* ...