一、自定义注解
一、自定义注解的配置
如果是用的配置文件需要在配置文件中添加配置:
<aop:aspectj-autoproxy/>
如果是使用类进行初始化加载需要在类的上面添加注解
@EnableAspectJAutoProxy
二、自定义注解的约束
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
三、自定义注解的模板
/**
* 自定义日志注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
/**
* operationType 操作类型
* dataType 数据类型
*/
public @interface MonitorLog {
String operationType() default "";
String dataType() default "";
}
1、@Target的用法
java.lang.annotation.Target
用于设定注解使用范围
java.lang.annotation.ElementType
Target通过ElementType来指定注解可使用范围的枚举集合
ElementType的用法
取值 | 注解使用范围 |
METHOD | 可用于方法上 |
TYPE | 可用于类或者接口上 |
ANNOTATION_TYPE | 可用于注解类型上(被@interface修饰的类型) |
CONSTRUCTOR | 可用于构造方法上 |
FIELD | 可用于域上 |
LOCAL_VARIABLE | 可用于局部变量上 |
PACKAGE | 用于记录java文件的package信息 |
PARAMETER | 可用于参数上 |
这里重点说明下:ElementType. PACKAGE。它并不是使用在一般的类中,而是用在固定的文件package-info.java中。这里需要强调命名一定是“package-info”。由于package-info.java并不是一个合法的类,使用eclipse创建类的方式会提示不合法,所以需要以创建文件的方式来创建package-info.java。
例如,定义可使用范围PACKAGE:
1
2
3
4
5
6
7
|
@Target
({ElementType.PACKAGE,ElementType.METHOD})
@Retention
(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public
@interface
AsynLog {
}
|
那么,创建文件:package-info.java,内容如下:
@AsynLog
package org.my.commons.logs.annotation;
2、Retention注解
Retention(保留)注解说明,这种类型的注解会被保留到那个阶段. 有三个值:
1.RetentionPolicy.SOURCE —— 这种类型的Annotations只在源代码级别保留,编译时就会被忽略
2.RetentionPolicy.CLASS —— 这种类型的Annotations编译时被保留,在class文件中存在,但JVM将会忽略
3.RetentionPolicy.RUNTIME —— 这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用.
3、Documented 注解
Documented 注解表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中. 示例6进一步演示了使用 @Documented:
二、切点为注解方式的AOP
一、设置切点为注解
/**
* 切点位置
*/
@Pointcut(value = "@annotation(com.xx.xx.log.MonitorLog)")
public void pointMethod() {
}
二、获取切点注解中的参数
@AfterReturning(value = "@annotation(ml)",argNames="ml")
public void afterMethodNormally(MonitorLog ml) {
String operationType = ml.operationType();
String dataType = ml.dataType();
}
三、获取切点方法中的参数
@After(value = "pointMethod()")
public void afterMethod(JoinPoint joinPoint) {
//获取方法名
String methodname = joinPoint.getSignature().getName();
//获取类名
String classname = joinPoint.getTarget().getClass().getName();
System.out.println("执行类名:"+classname+" 执行方法: "+methodName);
}
四、AOP注解
* @Before 在方法执行前 * @AfterReturning 在方法正常执行之后 * @AfterThrowing 在方法发生异常时执行的方法 * @After 在方法执行之后执行,无论是否发生异常
五、基于JoinPoint获取方法上的注解
/**
* 当方法正常执行结束后将当前的方法中的信息进行存储
*/
@AfterReturning(value = "pointMethod()")
public void afterMethodNormally(JoinPoint joinPoint) {
//获取操作时间
String time = getCurrentTime();
try{
//初始化封装对象
DownloadRecord dr = new DownloadRecord();
//封装时间信息
dr.setDownloadTime(new Date());
//获取session中用户信息
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
SecurityContextImpl securityContextImpl = (SecurityContextImpl) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
User user = (User)securityContextImpl.getAuthentication().getPrincipal();
//封装用户信息
dr.setDownloadUserId(user.getNickName());
dr.setDownloadUserName(user.getUsername());
//获取下载类型
//获取当前方法
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature)signature;
Method targetMethod = methodSignature.getMethod();
//获取方法上的注解
DownloadAnnotation da = targetMethod.getAnnotation(DownloadAnnotation.class);
String downloadType = da.downloadType();
//封装下载类型
dr.setDownloadType(downloadType);
//获取录音uuid
Object[] args = joinPoint.getArgs();
//封装录音信息
if(args != null && args.length > 0) {
dr.setVoiceName(String.valueOf(args[0]));
dr.setVoiceNumber(String.valueOf(args[0]));
}
logger.info("下载时间为:"+time+" 下载用户为:"+user.getUsername()
+" 下载类型为:"+downloadType+" 下载标识为:"+args[0]);
//保存下载信息
downloadRecordDao.save(dr);
} catch (Exception e) {
e.printStackTrace();
logger.error("获取下载记录时的执行AfterReturning发生异常,时间为:"+time);
//为了事务回滚 抛出运行时异常
throw new RuntimeException("获取下载记录时发生异常");
}
}
六、获取返回值
@AfterReturning(value = "pointcut() && @annotation(operateLog)", returning = "result")
public Object afterReturning(JoinPoint jionPoint, OperateLog operateLog, Object result){
System.out.println(jionPoint.getArgs());
String methodName = jionPoint.getSignature().getName();
System.out.println(methodName);
System.out.println(operateLog.operateType());
return result;
}