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
方法执行结束...
AOP切面详解的更多相关文章
- spring框架 AOP核心详解
AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...
- Spring系列25:Spring AOP 切点详解
本文内容 Spring 10种切点表达式详解 切点的组合使用 公共切点的定义 声明切点@Poincut @Poincut 的使用格式如下: @Poincut("PCD") // 切 ...
- Spring——面向切面编程(AOP)详解
声明:本博客仅仅是一个初学者的学习记录.心得总结,其中肯定有许多错误,不具有参考价值,欢迎大佬指正,谢谢!想和我交流.一起学习.一起进步的朋友可以加我微信Liu__66666666 这是简单学习一遍之 ...
- Spring框架学习-Spring的AOP概念详解
一.SpringAOP的概述. AOP(Aspect Oriented Programming),面向切面编程,通过预编译方式和运行期间动态代理实现程序的功能的统一维护的技术.AOP是OOP(面向对象 ...
- Spring AOP全面详解(超级详细)
如果说 IOC 是 Spring 的核心,那么面向切面编程AOP就是 Spring 另外一个最为重要的核心@mikechen AOP的定义 AOP (Aspect Orient Programming ...
- SPRING AOC、AOP 概念详解
AOC 依赖注入:就是通过容器来控制业务对象之间的依赖关系.也就是把需要的业务对象都放入容器中,需要注入时,通过反射技术来动态获取指定的对象,装配到当前使用对象.代替了原始的 new 来实现对象的实例 ...
- Spring框架学习05——AOP相关术语详解
1.Spring AOP 的基本概述 AOP(Aspect Oriented Programing)面向切面编程,AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视.事务管理.安全检查 ...
- [转载] 多图详解Spring框架的设计理念与设计模式
转载自http://developer.51cto.com/art/201006/205212_all.htm Spring作为现在最优秀的框架之一,已被广泛的使用,51CTO也曾经针对Spring框 ...
- Spring框架系列(9) - Spring AOP实现原理详解之AOP切面的实现
前文,我们分析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的.本文主要介绍Spring AOP原理解析的切面实现过程(将切面类的所 ...
随机推荐
- [BZOJ3236]:[Ahoi2013]作业(莫队+分块)
题目传送门 题目描述 此时已是凌晨两点,刚刚做了$Codeforces$的小$A$掏出了英语试卷.英语作业其实不算多,一个小时刚好可以做完.然后是一个小时可与做完的数学作业,接下来是分别都是一个小时可 ...
- 纯css实现手机通讯录
我们经常在手机上看到通讯录列表,这类布局一般有两个显著的效果 首字母吸顶 快速定位 下面我们来实现一下 页面结构 这里页面结构很简单,就是两个列表 <div class="con&qu ...
- MacOS上zsh环境设置默认jdk
进入home目录 cd ~ 修改.zprofile文件 vi .zprofile 按i进入vim插入模式,添加以下代码 export JAVA_HOME="/Library/Java/Jav ...
- SQLSTATE[HY000] [2002] No such file or directory
正常的解决办法.. 只需将laravel配置文件中的host 127.0.0.1改成localhost就可以: 'mysql' => array( 'driver' ...
- vi不能使用jk 映射?
vi不能使用jk 映射? 因为vi 不支持inormap 这种键映射! 要安装vim-enhanced后才能使用vim命令, 也才能够使用 键映射!
- 【C++进阶:STL常见性质3】
STL3个代表性函数:for_each(), random_shuffle(), sort() vector<int> stuff; random_shuffle(stuff.begin( ...
- MySQL的常用JSON函数
1. JSON_SEARCH(col ->> '$[*].key', type, val) col: JSON格式的字段名 key:要搜索的col字段的key type:可以为'one'或 ...
- 测开之路一百二十三:快速搭建python虚拟环境
前提:已装好python3.4+且环境可正常运行 一:手动搭建: 准备好一个工作目录 管理员运行cmd,进入到准备的目录里面 执行命令:python -m venv 虚拟环境名 激活虚拟环境(在ven ...
- PHP 实现并发-进程控制 PCNTL
参考 基于PCNTL的PHP并发编程 PCNTL 是 PHP 中的一组进程控制函数,可以用来 fork(创建)进程,传输控制信号等. 在PHP中,进程控制支持默认关闭.编译时通过 --enable-p ...
- c# thread4——lock,死锁,以及monitor关键字
多线程的存在是提高系统效率,挖掘cpu性能的一种手段,那么控制它,能够协同多个线程不发生bug是关键. 首先我们来看一段不安全的多线程代码. public abstract class Calcula ...