在spring中,我们可以看到各种各样的注解,例
一、为什么要使用自定义注解
在spring中,我们可以看到各种各样的注解,例如常见的component、controller、service、repository等等。这些注解最大的作用就是标识某个类或某个方法是否交给spring去管理,那么当我们想要对我们自己的类或方法进去某些标识的时候,就可以用到自定义注解。我比较常用到自定义注解的情景如:利用AOP做切面,切日志切权限的时候,往往需要一个标识却判断哪些需要加日志,哪些接口是拥有什么样的权限才能访问等等。
二、如何实现自定义注解
简单讲一下,一般注解就像一般的类只不过public class 换成了 public @interface ,然后头上一般会有两个注解,一个是Target(),这个目标对象,也就是说要对什么类型的起作用,如ElementType.METHOD即对方法起效,也就是这个注解只能用在方法上,还有加在类上的,自己有兴趣可以了解一下。@Retention即注解的生命周期,也就是注解能存活到什么时候。source:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;被编译器忽略class:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在。然后详细代码如下,很简单,基本上有点基础的小伙伴都能看懂,有疑问可以底部留言!
package com.pratice.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
String content();
}
二、使用AOP配置日志切面
最后写一个自定义注解的应用场景-----AOP做日志切面,AOP是spring的核心之一,有了解spring的小伙伴应该都清楚,不了解的小伙伴也可以百度一下,AOP也算是spring中的一大块,我几句话也说不清,后续有时间会出一期关于AOP的详细讲解,这里不多做陈述。首先可以pointcut切点和Before或者AfterRuring分开写,也可以如第二段代码一样合起来一起写,直接在环绕通知@Around(“execution(* com.pratice.controller..(…))”)里写上要切入的地方,如这里就是在进入到 com.pratice下所有的controller前都要进行日志记录。
package com.pratice.aop;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
@Component
@Aspect
@Slf4j
public class AOPLog {
private long start = 0;
@Pointcut("execution(* com.pratice.controller.*.*(..))")
public void haha(){}
@Before("haha()")
public void before(JoinPoint point){
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
HttpServletResponse response = requestAttributes.getResponse();
String addr = request.getRemoteAddr();
String uri = request.getRequestURI();
Object[] args = point.getArgs();
start = System.currentTimeMillis();
log.info("===================请求的地址是:================="+addr);
log.info("===================请求的路径是:================="+uri);
log.info("===================请求的参数是:================="+ Arrays.toString(args));
}
@AfterReturning("haha()")
public void after(){
long end = System.currentTimeMillis();
log.info("=================耗时================="+ (end-start));
log.info("=================结束了=================");
}
}
package com.pratice.aop;
import com.pratice.annotation.MyLog;
import com.pratice.dao.SysOperationLogDao;
import com.pratice.entity.SysEmpInfo;
import com.pratice.entity.SysOperationLog;
import com.pratice.result.Result;
import com.pratice.util.ShiroUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
@Component
@Aspect
public class OperationLog {
@Around("execution(* com.pratice.controller.*.*(..))")
public Result after(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
Result result = (Result) point.proceed(point.getArgs());
MyLog annotation = method.getAnnotation(MyLog.class);
if(annotation != null){
System.out.println("小伙伴们真帅");
}
return result;
}
}
|