自定义注解的实现

1.为什么要使用自定义注解?

使用Annotation之前(甚至在使用之后),XML被广泛的应用于描述元数据。

假如你想为应用设置很多的常量或参数,这种情况下,XML是一个很好的选择,因为它不会同特定的代码相连。如果你想把某个方法声明为服务,那么使用Annotation会更好一些,因为这种情况下需要注解和方法紧密耦合起来。

Spring为我们提供了面向切面编程的思想,我们就可以自己使用自定义注解解决一些问题。

2.自定义注解使用场景

打日志、分析代码执行时间、权限控制、事务处理、访问频率控制、异常处理等等。

Note:就和普通的注解实现的功能一样

2.1 自定义注解实现日志记录

一、写一个自定义注解

注解中包括配置方法所在模块名称,以及功能名称,当然我们在注解里可以自定义。

import java.lang.annotation.Documented;
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)
@Documented
public @interface Log {
    
    /** 模块 */
    String title() default "";
 
    /** 功能 */
    String action() default "";
    
}

二、建切面类

切面类里面定义好切点配置,以及所有的需要实现的通知方法。

 
import java.lang.reflect.Method;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
 
@Aspect
@Component("logAspect")
public class LogAspect {
 
    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
 
    // 配置织入点
    @Pointcut("@annotation(com.test.aspact.Log)")
    public void logPointCut() {
    }
 
    /**
     * 前置通知 用于拦截操作,在方法返回后执行
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut = "logPointCut()")
    public void doBefore(JoinPoint joinPoint) {
	handleLog(joinPoint, null);
    }
 
    /**
     * 拦截异常操作,有异常时执行
     * 
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void doAfter(JoinPoint joinPoint, Exception e) {
	handleLog(joinPoint, e);
    }
 
    private void handleLog(JoinPoint joinPoint, Exception e) {
	try {
	    // 获得注解
	    Log controllerLog = getAnnotationLog(joinPoint);
	    if (controllerLog == null) {
		return;
	    }
	    // 获得方法名称
	    String className = joinPoint.getTarget().getClass().getName();
	    String methodName = joinPoint.getSignature().getName();
	    String action = controllerLog.action();
	    String title = controllerLog.title();
	    //打印日志,如有需要还可以存入数据库
	    log.info(">>>>>>>>>>>>>模块名称:{}",title);
	    log.info(">>>>>>>>>>>>>操作名称:{}",action);
	    log.info(">>>>>>>>>>>>>类名:{}",className);
	    log.info(">>>>>>>>>>>>>方法名:{}",methodName);
	} catch (Exception exp) {
	    // 记录本地异常日志
	    log.error("==前置通知异常==");
	    log.error("异常信息:{}", exp.getMessage());
	    exp.printStackTrace();
	}
    }
 
    /**
     * 是否存在注解,如果存在就获取
     */
    private static Log getAnnotationLog(JoinPoint joinPoint) throws Exception {
	Signature signature = joinPoint.getSignature();
	MethodSignature methodSignature = (MethodSignature) signature;
	Method method = methodSignature.getMethod();
	if (method != null) {
	    return method.getAnnotation(Log.class);
	}
	return null;
    }
}

三、spring.xml配置

在spring的配置文件中,开启注解的扫描,开启切面扫描。

    <context:component-scan base-package="com.test.**"/>
	
    <mvc:annotation-driven  />
	
    <aop:aspectj-autoproxy />
	   
    <aop:config proxy-target-class="true"></aop:config>

四、测试Controller

@Controller
public class HelloController {
    
 
    private static final Logger log = LoggerFactory.getLogger(HelloController.class);
    
    @RequestMapping("/hello")
    //对应的自定义注解,当方法上写这个注解时,就会进入切面类中
    @Log(title="哈喽模块",action="say哈喽")
    public String sayHello() {
	log.info("HelloController sayHello:{}","hello world!");
	return "hello";
    }
}

测试结果:

输入网址http://localhost/test-demo/hello,进入hello.jsp

看结果可知,先输出了方法里的日志,在返回之后进入了切面方法,打印一出了自定义注解的信息,以及方法具体信息。

原文出处:https://blog.csdn.net/weixin_42184707/article/details/80348103

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值